@@ -45,7 +45,6 @@ interface Props {
45
45
onNewSQL : ( ) => void
46
46
controlsHidden : boolean
47
47
isFullScreen : boolean
48
- renderer ?: 'canvas' | 'svg'
49
48
isHidden : boolean
50
49
onToggleHidden : ( ) => void
51
50
onExportToPNG ?: ( ) => void
@@ -70,7 +69,6 @@ function VisualizationViewV2(props: Props) {
70
69
< BrieferResult
71
70
title = { props . title }
72
71
result = { props . result }
73
- renderer = { props . renderer }
74
72
input = { props . input }
75
73
hasControls = { props . hasControls }
76
74
/>
@@ -182,11 +180,10 @@ function BrieferResult(props: {
182
180
input : VisualizationV2BlockInput
183
181
hasControls : boolean
184
182
result : VisualizationV2BlockOutputResult
185
- renderer ?: 'canvas' | 'svg'
186
183
} ) {
187
184
const [ size , setSize ] = useResettableState (
188
185
( ) => null as { width : number ; height : number } | null ,
189
- [ props . result , props . renderer ]
186
+ [ props . result ]
190
187
)
191
188
192
189
const measureDiv = useRef < HTMLDivElement > ( null )
@@ -256,6 +253,7 @@ function BrieferResult(props: {
256
253
257
254
return {
258
255
...props . result ,
256
+ backgroundColor : '#fff' ,
259
257
legend : {
260
258
...props . result . legend ,
261
259
padding : props . hasControls
@@ -274,7 +272,8 @@ function BrieferResult(props: {
274
272
xAxis : props . result . xAxis . map ( ( axis ) => ( {
275
273
...axis ,
276
274
axisLabel : {
277
- hideOverlap : true ,
275
+ hideOverlap : axis . type !== 'category' ,
276
+ interval : axis . type === 'category' ? 0 : 'auto' ,
278
277
} ,
279
278
splitLine : {
280
279
show : false ,
@@ -315,12 +314,7 @@ function BrieferResult(props: {
315
314
316
315
return (
317
316
< div ref = { container } className = "ph-no-capture h-full" >
318
- < Echarts
319
- width = { size . width }
320
- height = { size . height }
321
- option = { option }
322
- renderer = { props . renderer }
323
- />
317
+ < Echarts width = { size . width } height = { size . height } option = { option } />
324
318
</ div >
325
319
)
326
320
}
@@ -329,32 +323,128 @@ interface EchartsProps {
329
323
width : number
330
324
height : number
331
325
option : echarts . EChartsOption
332
- renderer ?: 'canvas' | 'svg'
333
326
}
334
327
function Echarts ( props : EchartsProps ) {
335
328
const ref = useRef < HTMLDivElement > ( null )
336
- const [ chart , setChart ] = useState < echarts . ECharts | null > ( null )
329
+ const hiddenRef = useRef < HTMLDivElement > ( null )
330
+ const [ finalOption , setFinalOption ] = useState ( props . option )
331
+ const [ isReady , setIsReady ] = useState ( false )
337
332
333
+ // First render in hidden div to calculate layout
338
334
useEffect ( ( ) => {
339
- if ( ! ref . current ) {
340
- return
335
+ if ( ! hiddenRef . current ) return
336
+
337
+ const hiddenChart = echarts . init ( hiddenRef . current , null , {
338
+ renderer : 'svg' ,
339
+ } )
340
+ hiddenChart . setOption ( {
341
+ ...props . option ,
342
+ // set animation to be as fast as possible, since finished event does not get fired when no animation
343
+ animationDelay : 0 ,
344
+ animationDuration : 1 ,
345
+ } )
346
+
347
+ const handleFinished = ( ) => {
348
+ const xAxes = Array . isArray ( props . option . xAxis )
349
+ ? props . option . xAxis
350
+ : props . option . xAxis
351
+ ? [ props . option . xAxis ]
352
+ : [ ]
353
+ let isRotated = false
354
+ const nextXAxes = xAxes . map ( ( xAxis ) => {
355
+ if ( ! xAxis || xAxis . type !== 'category' ) {
356
+ return xAxis
357
+ }
358
+
359
+ const labels = hiddenChart . getZr ( ) . dom ?. querySelectorAll ( 'text' ) ?? [ ]
360
+ let hasOverlap = false
361
+
362
+ for ( let i = 0 ; i < labels . length - 1 ; i ++ ) {
363
+ const rect1 = labels [ i ] . getBoundingClientRect ( )
364
+ const rect2 = labels [ i + 1 ] . getBoundingClientRect ( )
365
+ if (
366
+ rect1 . right > rect2 . left &&
367
+ rect1 . left < rect2 . right &&
368
+ rect1 . bottom > rect2 . top &&
369
+ rect1 . top < rect2 . bottom
370
+ ) {
371
+ hasOverlap = true
372
+ break
373
+ }
374
+ }
375
+
376
+ if ( hasOverlap ) {
377
+ isRotated = true
378
+ return {
379
+ ...xAxis ,
380
+ axisLabel : {
381
+ ...xAxis . axisLabel ,
382
+ rotate : 45 ,
383
+ } ,
384
+ }
385
+ }
386
+ return xAxis
387
+ } )
388
+
389
+ setFinalOption ( {
390
+ ...props . option ,
391
+ xAxis : nextXAxes ,
392
+ // if isRotated we need additional padding left
393
+ grid : props . option . grid
394
+ ? Array . isArray ( props . option . grid )
395
+ ? props . option . grid . map ( ( grid ) => ( {
396
+ ...grid ,
397
+ left : isRotated ? '60' : grid . left ,
398
+ } ) )
399
+ : {
400
+ ...props . option . grid ,
401
+ left : isRotated ? '60' : props . option . grid . left ,
402
+ }
403
+ : isRotated
404
+ ? {
405
+ left : '60' ,
406
+ }
407
+ : undefined ,
408
+ } )
409
+ setIsReady ( true )
410
+ hiddenChart . dispose ( )
341
411
}
342
412
343
- const chart = echarts . init ( ref . current , { renderer : props . renderer } )
344
- setChart ( chart )
413
+ hiddenChart . on ( 'finished' , handleFinished )
345
414
346
415
return ( ) => {
347
- chart . dispose ( )
416
+ hiddenChart . dispose ( )
348
417
}
349
- } , [ ref . current , props . renderer ] )
418
+ } , [ props . option ] )
350
419
420
+ // Only render the visible chart once we have the final layout
351
421
useEffect ( ( ) => {
352
- if ( chart ) {
353
- chart . setOption ( props . option )
422
+ if ( ! ref . current || ! isReady ) {
423
+ return
354
424
}
355
- } , [ props . option , chart ] )
356
425
357
- return < div ref = { ref } className = "w-full h-full" />
426
+ const chart = echarts . init ( ref . current , null , { renderer : 'canvas' } )
427
+ chart . setOption ( finalOption )
428
+
429
+ return ( ) => {
430
+ chart . dispose ( )
431
+ }
432
+ } , [ ref . current , isReady , finalOption ] )
433
+
434
+ return (
435
+ < >
436
+ < div
437
+ ref = { hiddenRef }
438
+ className = "w-full h-full"
439
+ style = { {
440
+ position : 'absolute' ,
441
+ visibility : 'hidden' ,
442
+ pointerEvents : 'none' ,
443
+ } }
444
+ />
445
+ { isReady && < div ref = { ref } className = "w-full h-full" /> }
446
+ </ >
447
+ )
358
448
}
359
449
360
450
function BigNumberVisualization ( props : {
0 commit comments