1
1
import React from 'react'
2
2
import useChartState from '../hooks/useChartState'
3
3
import useIsomorphicLayoutEffect from '../hooks/useIsomorphicLayoutEffect'
4
- import usePrevious from '../hooks/usePrevious '
4
+ import { axisTypeOrdinal } from '../utils/Constants '
5
5
import { round } from '../utils/Utils'
6
6
7
- const radiansToDegrees = r => r * ( 180 / Math . PI )
8
- const degreesToRadians = d => d * ( Math . PI / 180 )
9
-
10
7
const getElBox = el => {
11
8
var rect = el . getBoundingClientRect ( )
12
9
return {
@@ -30,8 +27,6 @@ export default function useMeasure({
30
27
position,
31
28
tickSizeInner,
32
29
tickSizeOuter,
33
- transform,
34
- barSize,
35
30
labelRotation,
36
31
tickPadding,
37
32
tickCount,
@@ -40,19 +35,20 @@ export default function useMeasure({
40
35
vertical,
41
36
gridWidth,
42
37
gridHeight,
43
- ticks,
44
- scale,
45
38
} ) {
46
- const disallowListRef = React . useRef ( [ ] )
47
- const axisDimensionsHistoryRef = React . useRef ( [ ] )
48
-
49
- const [ axisDimensions , setChartState ] = useChartState (
50
- state => state . axisDimensions
39
+ const [ estimatedTickCount , setChartState ] = useChartState (
40
+ state => state . estimatedTickCounts [ id ]
41
+ )
42
+ const [ tickLabelSkipRatio ] = useChartState (
43
+ state => state . tickLabelSkipRatios [ id ]
44
+ )
45
+ const [ axisDimension ] = useChartState (
46
+ state => state . axisDimensions ?. [ position ] ?. [ id ]
51
47
)
52
48
53
49
const measureDimensions = React . useCallback ( ( ) => {
54
50
if ( ! elRef . current ) {
55
- if ( axisDimensions [ position ] ?. [ id ] ) {
51
+ if ( axisDimension ) {
56
52
// If the entire axis is hidden, then we need to remove the axis dimensions
57
53
setChartState ( state => {
58
54
const newAxes = state . axisDimensions [ position ] || { }
@@ -70,30 +66,13 @@ export default function useMeasure({
70
66
}
71
67
72
68
let gridSize = ! vertical ? gridWidth : gridHeight
73
- let calculatedTickCount = tickCount
74
69
let width = 0
75
70
let height = 0
76
71
let top = 0
77
72
let bottom = 0
78
73
let left = 0
79
74
let right = 0
80
75
81
- // Measure the distances between ticks
82
- let smallestTickGap = gridSize // This is just a ridiculously large tick spacing that would never happen (hopefully)
83
-
84
- Array ( ...elRef . current . querySelectorAll ( '.tick' ) )
85
- . map ( el => getElBox ( el ) )
86
- . reduce ( ( prev , current ) => {
87
- if ( prev ) {
88
- smallestTickGap = Math . min (
89
- smallestTickGap ,
90
- vertical ? current . top - prev . top : current . left - prev . left
91
- )
92
- }
93
-
94
- return current
95
- } , false )
96
-
97
76
const domainDims = getElBox ( elRef . current . querySelector ( '.domain' ) )
98
77
99
78
const measureLabelDims = Array (
@@ -134,26 +113,70 @@ export default function useMeasure({
134
113
[ ]
135
114
)
136
115
137
- // Auto-fit ticks in "auto" tick mode
138
- if ( tickCount === 'auto' && type !== 'ordinal' ) {
139
- const largestMeasureLabelSize = ! vertical
140
- ? widestMeasureLabel ?. width || 0
141
- : tallestMeasureLabel ?. height || 0
116
+ let smallestTickGap = gridSize
117
+
118
+ if ( measureLabelDims . length > 1 ) {
119
+ measureLabelDims . reduce ( ( prev , current ) => {
120
+ if ( prev ) {
121
+ smallestTickGap = Math . min (
122
+ smallestTickGap ,
123
+ vertical ? current . top - prev . top : current . left - prev . left
124
+ )
125
+ }
126
+
127
+ return current
128
+ } , false )
129
+ }
142
130
131
+ const largestMeasureLabelSize = ! vertical
132
+ ? widestMeasureLabel ?. width || 0
133
+ : tallestMeasureLabel ?. height || 0
134
+
135
+ // Auto-fit ticks in "auto" tick mode for non-ordinal scales
136
+ if ( tickCount === 'auto' && type !== 'ordinal' ) {
143
137
// if it's on, determine how many ticks we could display if they were all flat
144
138
// How many ticks can we fit in the available axis space?
145
- const estimatedTickCount = Math . floor (
146
- ( gridSize + largestMeasureLabelSize + tickPadding ) /
147
- ( largestMeasureLabelSize + tickPadding )
139
+ let calculatedTickCount = Math . floor (
140
+ ( gridSize + largestMeasureLabelSize + tickPadding * 2 ) /
141
+ ( largestMeasureLabelSize + tickPadding * 2 )
148
142
)
149
143
150
144
calculatedTickCount = Math . max (
151
- Math . min ( estimatedTickCount , maxTickCount ) ,
145
+ Math . min ( calculatedTickCount , maxTickCount ) ,
152
146
minTickCount
153
147
)
148
+
149
+ if ( calculatedTickCount !== estimatedTickCount ) {
150
+ setChartState ( old => ( {
151
+ ...old ,
152
+ estimatedTickCounts : {
153
+ ...old . estimatedTickCounts ,
154
+ [ id ] : calculatedTickCount ,
155
+ } ,
156
+ } ) )
157
+ }
154
158
}
155
159
156
- if ( ! vertical ) {
160
+ // Visual Skipping of axis labels if they overlap (rotation not included)
161
+ const newTickLabelSkipRatio = ! rotation
162
+ ? Math . max (
163
+ 1 ,
164
+ Math . ceil ( ( largestMeasureLabelSize + tickPadding ) / smallestTickGap )
165
+ )
166
+ : 1
167
+
168
+ if ( newTickLabelSkipRatio !== tickLabelSkipRatio ) {
169
+ setChartState ( old => ( {
170
+ ...old ,
171
+ tickLabelSkipRatios : {
172
+ ...old . tickLabelSkipRatios ,
173
+ [ id ] : newTickLabelSkipRatio ,
174
+ } ,
175
+ } ) )
176
+ }
177
+
178
+ // Rotate ticks for non-time horizontal axes
179
+ if ( ! vertical && type === axisTypeOrdinal ) {
157
180
const newRotation =
158
181
( widestMeasureLabel ?. width || 0 ) + tickPadding > smallestTickGap
159
182
? labelRotation
@@ -166,12 +189,16 @@ export default function useMeasure({
166
189
167
190
// Axis overflow measurements
168
191
if ( ! vertical ) {
169
- const leftMostLabelDim = realLabelDims . reduce ( ( d , labelDim ) =>
170
- labelDim . left < d . left ? labelDim : d
171
- )
172
- const rightMostLabelDim = realLabelDims . reduce ( ( d , labelDim ) =>
173
- labelDim . right > d . right ? labelDim : d
174
- )
192
+ const leftMostLabelDim = realLabelDims . length
193
+ ? realLabelDims . reduce ( ( d , labelDim ) =>
194
+ labelDim . left < d . left ? labelDim : d
195
+ )
196
+ : null
197
+ const rightMostLabelDim = realLabelDims . length
198
+ ? realLabelDims . reduce ( ( d , labelDim ) =>
199
+ labelDim . right > d . right ? labelDim : d
200
+ )
201
+ : null
175
202
176
203
left = round (
177
204
Math . max ( 0 , domainDims . left - leftMostLabelDim ?. left ) ,
@@ -229,14 +256,13 @@ export default function useMeasure({
229
256
bottom,
230
257
left,
231
258
right,
232
- tickCount : calculatedTickCount ,
233
259
}
234
260
235
261
// Only update the axisDimensions if something has changed
236
262
if (
237
- ! axisDimensions ?. [ position ] ?. [ id ] ||
263
+ ! axisDimension ||
238
264
Object . keys ( newDimensions ) . some ( key => {
239
- return newDimensions [ key ] !== axisDimensions [ position ] [ id ] [ key ]
265
+ return newDimensions [ key ] !== axisDimension [ key ]
240
266
} )
241
267
) {
242
268
setChartState ( state => ( {
@@ -251,8 +277,9 @@ export default function useMeasure({
251
277
} ) )
252
278
}
253
279
} , [
254
- axisDimensions ,
280
+ axisDimension ,
255
281
elRef ,
282
+ estimatedTickCount ,
256
283
gridHeight ,
257
284
gridWidth ,
258
285
id ,
@@ -264,6 +291,7 @@ export default function useMeasure({
264
291
setChartState ,
265
292
setRotation ,
266
293
tickCount ,
294
+ tickLabelSkipRatio ,
267
295
tickPadding ,
268
296
tickSizeInner ,
269
297
tickSizeOuter ,
0 commit comments