Skip to content

Commit 9e55362

Browse files
committed
fix: 添加全屏功能至图表组件,优化用户交互体验
1 parent c06700a commit 9e55362

File tree

2 files changed

+111
-61
lines changed

2 files changed

+111
-61
lines changed

src/plugins/chart/ChartMark/Container.tsx

+1
Original file line numberDiff line numberDiff line change
@@ -76,6 +76,7 @@ export const Container: React.FC<{
7676
ref={htmlRef}
7777
onClick={onSize}
7878
style={{
79+
height: 'calc(100% - 48px)',
7980
maxHeight: `max(${htmlRef.current?.clientWidth || 400}px, 400px)`,
8081
}}
8182
/>

src/plugins/chart/ChartRender.tsx

+110-61
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import {
22
DownloadOutlined,
33
DownOutlined,
4+
FullscreenOutlined,
45
ReloadOutlined,
56
SettingOutlined,
67
} from '@ant-design/icons';
@@ -10,6 +11,7 @@ import { ConfigProvider, Descriptions, Dropdown, Popover, Table } from 'antd';
1011
import { DescriptionsItemType } from 'antd/es/descriptions';
1112
import React, { useMemo, useRef, useState } from 'react';
1213
import { ActionIconBox } from '../../MarkdownEditor/editor/components';
14+
import { useFullScreenHandle } from '../../MarkdownEditor/hooks/useFullScreenHandle';
1315
import { ChartAttrToolBar } from './ChartAttrToolBar';
1416
import { Area, Bar, Column, Line, Pie } from './ChartMark';
1517

@@ -85,6 +87,7 @@ export const ChartRender: React.FC<{
8587
columnLength?: number;
8688
onColumnLengthChange?: (value: number) => void;
8789
}> = (props) => {
90+
const handle = useFullScreenHandle();
8891
const [chartType, setChartType] = useState<
8992
'pie' | 'bar' | 'line' | 'column' | 'area' | 'descriptions' | 'table'
9093
>(() => props.chartType);
@@ -411,76 +414,122 @@ export const ChartRender: React.FC<{
411414
</div>
412415
);
413416
}
414-
}, [chartType, JSON.stringify(chartData), JSON.stringify(config)]);
417+
}, [
418+
chartType,
419+
JSON.stringify(chartData),
420+
handle.active,
421+
JSON.stringify(config),
422+
]);
415423

416424
const toolBar = getChartPopover();
417425

418426
if (!chartDom) return null;
427+
419428
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+
>
421435
<div
436+
ref={handle.node}
422437
style={{
423-
userSelect: 'none',
438+
background: '#fff',
439+
borderRadius: 'inherit',
424440
}}
425-
contentEditable={false}
426441
>
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}
482532
</div>
483-
{chartDom ?? null}
484-
</div>
533+
</ConfigProvider>
485534
);
486535
};

0 commit comments

Comments
 (0)