1
1
import {
2
2
DownloadOutlined ,
3
3
DownOutlined ,
4
+ FullscreenOutlined ,
4
5
ReloadOutlined ,
5
6
SettingOutlined ,
6
7
} from '@ant-design/icons' ;
@@ -10,6 +11,7 @@ import { ConfigProvider, Descriptions, Dropdown, Popover, Table } from 'antd';
10
11
import { DescriptionsItemType } from 'antd/es/descriptions' ;
11
12
import React , { useMemo , useRef , useState } from 'react' ;
12
13
import { ActionIconBox } from '../../MarkdownEditor/editor/components' ;
14
+ import { useFullScreenHandle } from '../../MarkdownEditor/hooks/useFullScreenHandle' ;
13
15
import { ChartAttrToolBar } from './ChartAttrToolBar' ;
14
16
import { Area , Bar , Column , Line , Pie } from './ChartMark' ;
15
17
@@ -85,6 +87,7 @@ export const ChartRender: React.FC<{
85
87
columnLength ?: number ;
86
88
onColumnLengthChange ?: ( value : number ) => void ;
87
89
} > = ( props ) => {
90
+ const handle = useFullScreenHandle ( ) ;
88
91
const [ chartType , setChartType ] = useState <
89
92
'pie' | 'bar' | 'line' | 'column' | 'area' | 'descriptions' | 'table'
90
93
> ( ( ) => props . chartType ) ;
@@ -411,76 +414,122 @@ export const ChartRender: React.FC<{
411
414
</ div >
412
415
) ;
413
416
}
414
- } , [ chartType , JSON . stringify ( chartData ) , JSON . stringify ( config ) ] ) ;
417
+ } , [
418
+ chartType ,
419
+ JSON . stringify ( chartData ) ,
420
+ handle . active ,
421
+ JSON . stringify ( config ) ,
422
+ ] ) ;
415
423
416
424
const toolBar = getChartPopover ( ) ;
417
425
418
426
if ( ! chartDom ) return null ;
427
+
419
428
return (
420
- < div >
429
+ < ConfigProvider
430
+ getPopupContainer = { ( node ) => ( handle . node . current || node ) as HTMLElement }
431
+ getTargetContainer = { ( ) =>
432
+ ( handle . node . current || document ?. body ) as HTMLElement
433
+ }
434
+ >
421
435
< div
436
+ ref = { handle . node }
422
437
style = { {
423
- userSelect : 'none' ,
438
+ background : '#fff' ,
439
+ borderRadius : 'inherit' ,
424
440
} }
425
- contentEditable = { false }
426
441
>
427
- < ChartAttrToolBar
428
- title = { title || '' }
429
- node = { node }
430
- options = { [
431
- {
432
- style : { padding : 0 } ,
433
- icon : toolBar . at ( 0 ) ,
434
- } ,
435
- {
436
- style : { padding : 0 } ,
437
- icon : toolBar . at ( 1 ) ,
438
- } ,
439
- {
440
- style : { padding : 0 } ,
441
- icon : toolBar . at ( 2 ) ,
442
- } ,
443
- {
444
- style : { padding : 0 } ,
445
- icon : (
446
- < ActionIconBox
447
- title = "重新渲染"
448
- onClick = { ( ) => chartRef . current ?. render ( ) }
449
- >
450
- < ReloadOutlined />
451
- </ ActionIconBox >
452
- ) ,
453
- } ,
454
- {
455
- style : { padding : 0 } ,
456
- icon : (
457
- < ActionIconBox
458
- title = "下载"
459
- onClick = { ( ) => {
460
- const csvString = chartData
461
- . map ( ( item ) => {
462
- return Object . values ( item ) . join ( ',' ) ;
463
- } )
464
- . join ( '\n' ) ;
465
- const blob = new Blob ( [ csvString ] , {
466
- type : 'text/csv;charset=utf-8;' ,
467
- } ) ;
468
- const url = URL . createObjectURL ( blob ) ;
469
- const a = document . createElement ( 'a' ) ;
470
- a . href = url ;
471
- a . download = 'data.csv' ;
472
- a . click ( ) ;
473
- URL . revokeObjectURL ( url ) ;
474
- } }
475
- >
476
- < DownloadOutlined />
477
- </ ActionIconBox >
478
- ) ,
479
- } ,
480
- ] }
481
- />
442
+ < div
443
+ style = { {
444
+ userSelect : 'none' ,
445
+ } }
446
+ contentEditable = { false }
447
+ >
448
+ < ChartAttrToolBar
449
+ title = { title || '' }
450
+ node = { node }
451
+ options = { [
452
+ {
453
+ style : { padding : 0 } ,
454
+ icon : toolBar . at ( 0 ) ,
455
+ } ,
456
+ {
457
+ style : { padding : 0 } ,
458
+ icon : toolBar . at ( 1 ) ,
459
+ } ,
460
+ {
461
+ style : { padding : 0 } ,
462
+ icon : toolBar . at ( 2 ) ,
463
+ } ,
464
+ {
465
+ style : { padding : 0 } ,
466
+ icon : (
467
+ < ActionIconBox
468
+ title = "重新渲染"
469
+ onClick = { ( ) => chartRef . current ?. render ( ) }
470
+ >
471
+ < ReloadOutlined />
472
+ </ ActionIconBox >
473
+ ) ,
474
+ } ,
475
+ {
476
+ style : { padding : 0 } ,
477
+ icon : (
478
+ < ActionIconBox
479
+ title = "下载"
480
+ onClick = { ( ) => {
481
+ const csvString = chartData
482
+ . map ( ( item ) => {
483
+ return Object . values ( item ) . join ( ',' ) ;
484
+ } )
485
+ . join ( '\n' ) ;
486
+ const blob = new Blob ( [ csvString ] , {
487
+ type : 'text/csv;charset=utf-8;' ,
488
+ } ) ;
489
+ const url = URL . createObjectURL ( blob ) ;
490
+ const a = document . createElement ( 'a' ) ;
491
+ a . href = url ;
492
+ a . download = 'data.csv' ;
493
+ a . click ( ) ;
494
+ URL . revokeObjectURL ( url ) ;
495
+ } }
496
+ >
497
+ < DownloadOutlined />
498
+ </ ActionIconBox >
499
+ ) ,
500
+ } ,
501
+ {
502
+ style : { padding : 0 } ,
503
+ icon : (
504
+ < ActionIconBox
505
+ title = "全屏"
506
+ onClick = { ( e ) => {
507
+ e . stopPropagation ( ) ;
508
+ if ( handle . active ) {
509
+ handle . exit ( ) ;
510
+ setConfig ( props . config ) ;
511
+ } else {
512
+ handle . enter ( ) ;
513
+ setConfig ( {
514
+ ...props . config ,
515
+ height : undefined ,
516
+ } ) ;
517
+ }
518
+ } }
519
+ >
520
+ { handle . active ? (
521
+ < FullscreenOutlined />
522
+ ) : (
523
+ < FullscreenOutlined />
524
+ ) }
525
+ </ ActionIconBox >
526
+ ) ,
527
+ } ,
528
+ ] }
529
+ />
530
+ </ div >
531
+ { chartDom ?? null }
482
532
</ div >
483
- { chartDom ?? null }
484
- </ div >
533
+ </ ConfigProvider >
485
534
) ;
486
535
} ;
0 commit comments