Skip to content

Commit 6a244b1

Browse files
committed
feat: auto tick count
1 parent c26aaac commit 6a244b1

File tree

6 files changed

+1898
-1886
lines changed

6 files changed

+1898
-1886
lines changed

examples/simple/src/ResizableBox.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ export default function ResizableBox({
1212
className = "",
1313
}) {
1414
return (
15-
<div>
15+
<div style={{ marginLeft: 20 }}>
1616
{resizable ? (
1717
<ReactResizableBox width={width} height={height}>
1818
<div

src/components/AxisLinear.tsx

Lines changed: 19 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,20 +1,15 @@
1-
import { ScaleLinear, ScaleTime } from 'd3-scale'
21
import React from 'react'
32

4-
import { Axis, AxisTime } from '../types'
3+
import { Axis, AxisLinear } from '../types'
54
import { getTickPx, translate } from '../utils/Utils'
65
import useChartContext from '../utils/chartContext'
76
//
87
import useMeasure from './AxisLinear.useMeasure'
98

109
export default function AxisLinearComp<TDatum>(axis: Axis<TDatum>) {
1110
const [showRotated, setShowRotated] = React.useState(false)
12-
const {
13-
getOptions,
14-
gridDimensions,
15-
width,
16-
height,
17-
} = useChartContext<TDatum>()
11+
const { getOptions, gridDimensions, width, height } =
12+
useChartContext<TDatum>()
1813

1914
const { dark, showDebugAxes } = getOptions()
2015

@@ -34,15 +29,22 @@ export default function AxisLinearComp<TDatum>(axis: Axis<TDatum>) {
3429
const scale = isOuter ? axis.outerScale : axis.scale
3530
const [rangeStart, rangeEnd] = scale.range()
3631

37-
const getTicks = (
38-
scale: ScaleTime<any, any> | ScaleLinear<any, any>,
39-
num: number
40-
) => {
41-
if (scale.ticks) {
42-
return scale.ticks(num)
32+
const getTicks = () => {
33+
const anyAxis = axis as AxisLinear<TDatum>
34+
35+
if ((anyAxis as AxisLinear<TDatum>).outerScale.ticks!) {
36+
if (typeof anyAxis.tickCount === 'number') {
37+
return anyAxis.outerScale.ticks(anyAxis.tickCount)
38+
}
39+
40+
const autoSpacing = anyAxis.isVertical ? 40 : 80
41+
const range = anyAxis.outerScale.range()
42+
const num = Math.abs(range[1] - range[0]) / autoSpacing
43+
44+
return anyAxis.outerScale.ticks(num)
4345
}
4446

45-
return scale.domain()
47+
return anyAxis.outerScale.domain()
4648
}
4749

4850
const resolvedHeight = isOuter ? height : gridDimensions.gridHeight
@@ -101,7 +103,7 @@ export default function AxisLinearComp<TDatum>(axis: Axis<TDatum>) {
101103
y2={lineTo.y}
102104
stroke={dark ? 'rgba(255,255,255, .2)' : 'rgba(0,0,0, .2)'}
103105
/>
104-
{getTicks(scale as ScaleTime<any, any>, 10).map((tick, i) => {
106+
{getTicks().map((tick, i) => {
105107
const px = getTickPx(scale, tick)
106108

107109
const [tickFrom, tickTo, gridTo] =
@@ -187,7 +189,7 @@ export default function AxisLinearComp<TDatum>(axis: Axis<TDatum>) {
187189
isRotated ? (axis.position === 'top' ? 60 : -60) : 0
188190
})`}
189191
>
190-
{(axis as AxisTime<any>).formatters.scale(tick as Date)}
192+
{(axis as AxisLinear<any>).formatters.scale(tick as number)}
191193
</text>
192194
</g>
193195
)

src/components/AxisLinear.useMeasure.ts

Lines changed: 53 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -124,77 +124,93 @@ export default function useMeasure<TDatum>({
124124
right: 0,
125125
}
126126

127-
const domainEl = elRef.current.querySelector(`.Axis-Group.inner .domain`)
127+
const currentEl = elRef.current
128128

129-
if (!domainEl) {
130-
return
131-
}
129+
const [innerDims] = ['inner'].map(inOrOut => {
130+
const domainEl = currentEl.querySelector(`.Axis-Group.${inOrOut} .domain`)
132131

133-
const domainDims = getElBox(domainEl)
132+
if (!domainEl) {
133+
return
134+
}
134135

135-
const measureDims = Array.from(
136-
elRef.current.querySelectorAll('.Axis-Group.inner .tickLabel')
137-
).map(el => getElBox(el))
136+
const domainDims = getElBox(domainEl)
138137

139-
// Determine the largest labels on the axis
140-
let widestRealLabel = measureDims[0]
141-
let tallestRealLabel = measureDims[0]
138+
const measureDims = Array.from(
139+
currentEl.querySelectorAll(`.Axis-Group.${inOrOut} .tickLabel`)
140+
).map(el => getElBox(el))
142141

143-
measureDims.forEach(d => {
144-
if (d.width > 0 && d.width > widestRealLabel.width) {
145-
widestRealLabel = d
142+
if (!measureDims.length) {
143+
return
146144
}
147145

148-
if (d.height > 0 && d.height > tallestRealLabel.height) {
149-
tallestRealLabel = d
150-
}
146+
// Determine the largest labels on the axis
147+
let widestLabel = measureDims[0]
148+
let tallestLabel = measureDims[0]
149+
150+
measureDims.forEach(d => {
151+
if (d.width > 0 && d.width > widestLabel.width) {
152+
widestLabel = d
153+
}
154+
155+
if (d.height > 0 && d.height > tallestLabel.height) {
156+
tallestLabel = d
157+
}
158+
})
159+
160+
return { domainDims, measureDims, widestLabel, tallestLabel }
151161
})
152162

163+
if (!innerDims) {
164+
return
165+
}
166+
153167
// Axis overflow measurements
154168
if (!axis.isVertical) {
155-
if (measureDims.length) {
156-
const leftMostLabelDim = measureDims.reduce((d, labelDim) =>
169+
if (innerDims.measureDims.length) {
170+
const leftMostLabelDim = innerDims.measureDims.reduce((d, labelDim) =>
157171
labelDim.left < d.left ? labelDim : d
158172
)
159-
const rightMostLabelDim = measureDims.reduce((d, labelDim) =>
173+
const rightMostLabelDim = innerDims.measureDims.reduce((d, labelDim) =>
160174
labelDim.right > d.right ? labelDim : d
161175
)
162176

163177
newDimensions.left = Math.round(
164-
Math.max(0, domainDims.left - leftMostLabelDim?.left)
178+
Math.max(0, innerDims.domainDims.left - leftMostLabelDim?.left)
165179
)
166180

167181
newDimensions.right = Math.round(
168-
Math.max(0, rightMostLabelDim?.right - domainDims.right)
182+
Math.max(0, rightMostLabelDim?.right - innerDims.domainDims.right)
169183
)
170184
}
171185

172186
newDimensions.height = Math.round(
173187
// Math.max(axis.tickSizeInner, axis.tickSizeOuter) +
174-
8 + axis.minTickPaddingForRotation + (tallestRealLabel?.height ?? 0)
188+
8 +
189+
axis.minTickPaddingForRotation +
190+
(innerDims.tallestLabel?.height ?? 0)
175191
)
176192
} else {
177-
if (measureDims.length) {
178-
const topMostLabelDim = measureDims.reduce((d, labelDim) =>
193+
if (innerDims.measureDims.length) {
194+
const topMostLabelDim = innerDims.measureDims.reduce((d, labelDim) =>
179195
labelDim.top < d.top ? labelDim : d
180196
)
181197

182-
const bottomMostLabelDim = measureDims.reduce((d, labelDim) =>
198+
const bottomMostLabelDim = innerDims.measureDims.reduce((d, labelDim) =>
183199
labelDim.bottom > d.bottom ? labelDim : d
184200
)
185201

186202
newDimensions.top = Math.round(
187-
Math.max(0, domainDims.top - topMostLabelDim?.top)
203+
Math.max(0, innerDims.domainDims.top - topMostLabelDim?.top)
188204
)
189205

190206
newDimensions.bottom = Math.round(
191-
Math.max(0, bottomMostLabelDim?.bottom - domainDims.bottom)
207+
Math.max(0, bottomMostLabelDim?.bottom - innerDims.domainDims.bottom)
192208
)
193209
}
194210

195211
newDimensions.width = Math.round(
196212
// Math.max(axis.tickSizeInner, axis.tickSizeOuter) +
197-
8 + axis.minTickPaddingForRotation + (widestRealLabel?.width ?? 0)
213+
8 + axis.minTickPaddingForRotation + (innerDims.widestLabel?.width ?? 0)
198214
)
199215
}
200216

@@ -229,10 +245,16 @@ export default function useMeasure<TDatum>({
229245

230246
// Measure after if needed
231247
useIsomorphicLayoutEffect(() => {
232-
measureRotation()
248+
// setTimeout(() => {
249+
window.requestAnimationFrame(() => {
250+
measureRotation()
251+
})
233252
}, [measureRotation])
234253

235254
useIsomorphicLayoutEffect(() => {
236-
measureDimensions()
255+
// setTimeout(() => {
256+
window.requestAnimationFrame(() => {
257+
measureDimensions()
258+
})
237259
}, [measureRotation])
238260
}

src/components/Chart.tsx

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -433,17 +433,6 @@ function ChartInner<TDatum>({
433433
})
434434
}, [gridDimensions, height, secondaryAxesOptions, series, width])
435435

436-
const axesInfo: AxesInfo = React.useMemo(() => {
437-
// Make sure we're mapping x and y to the correct axes
438-
const xKey = primaryAxis.isVertical ? 'secondary' : 'primary'
439-
const yKey = primaryAxis.isVertical ? 'primary' : 'secondary'
440-
441-
return {
442-
xKey,
443-
yKey,
444-
}
445-
}, [primaryAxis])
446-
447436
const groupedDatums = React.useMemo(() => {
448437
const groupedDatums = new Map<any, Datum<TDatum>[]>()
449438

@@ -528,7 +517,6 @@ function ChartInner<TDatum>({
528517
gridDimensions,
529518
primaryAxis,
530519
secondaryAxes,
531-
axesInfo,
532520
series,
533521
orderedSeries,
534522
groupedDatums,

src/types.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -69,7 +69,6 @@ export type ChartContextValue<TDatum> = {
6969
gridDimensions: GridDimensions
7070
primaryAxis: Axis<TDatum>
7171
secondaryAxes: Axis<TDatum>[]
72-
axesInfo: AxesInfo
7372
series: Series<TDatum>[]
7473
orderedSeries: Series<TDatum>[]
7574
groupedDatums: Map<any, Datum<TDatum>[]>
@@ -225,6 +224,7 @@ export type AxisOptionsBase = {
225224
position?: Position
226225
minTickPaddingForRotation?: number
227226
tickLabelRotationDeg?: number
227+
tickCount?: number
228228
innerBandPadding?: number
229229
outerBandPadding?: number
230230
minBandSize?: number

0 commit comments

Comments
 (0)