fix: chart resize

This commit is contained in:
jialin
2024-10-23 18:04:34 +08:00
parent f5edf39027
commit 8576015633
9 changed files with 72 additions and 103 deletions
+30 -7
View File
@@ -1,4 +1,4 @@
import { throttle } from 'echarts/core'; import { throttle } from 'lodash';
import { useCallback, useEffect, useRef } from 'react'; import { useCallback, useEffect, useRef } from 'react';
import echarts, { ECOption } from '.'; import echarts, { ECOption } from '.';
@@ -9,6 +9,8 @@ const Chart: React.FC<{
}> = ({ options, width, height }) => { }> = ({ options, width, height }) => {
const container = useRef<HTMLDivElement>(null); const container = useRef<HTMLDivElement>(null);
const chart = useRef<echarts.EChartsType>(); const chart = useRef<echarts.EChartsType>();
const resizeable = useRef(false);
const resizeObserver = useRef<ResizeObserver>();
const init = useCallback(() => { const init = useCallback(() => {
if (container.current) { if (container.current) {
@@ -30,27 +32,48 @@ const Chart: React.FC<{
}, []); }, []);
useEffect(() => { useEffect(() => {
init(); if (container.current) {
init();
}
return () => { return () => {
chart.current?.dispose(); chart.current?.dispose();
}; };
}, [init]); }, [init]);
useEffect(() => { useEffect(() => {
resizeable.current = false;
resize(); resize();
setOption(options); setOption(options);
}, [options]); }, [options]);
// resize on window resize useEffect(() => {
let timer: any = null;
timer = setTimeout(() => {
resizeable.current = true;
}, 300);
return () => {
clearTimeout(timer);
};
}, []);
useEffect(() => { useEffect(() => {
const handleResize = throttle(() => { const handleResize = throttle(() => {
resize(); if (resizeable.current) {
chart.current?.resize();
}
}, 100); }, 100);
window.addEventListener('resize', handleResize);
if (container.current) {
resizeObserver.current = new ResizeObserver(handleResize);
resizeObserver.current.observe(container.current);
}
return () => { return () => {
window.removeEventListener('resize', handleResize); if (container.current) {
resizeObserver.current?.unobserve(container.current);
}
}; };
}, [resize]); }, []);
return <div ref={container} style={{ width: width, height }}></div>; return <div ref={container} style={{ width: width, height }}></div>;
}; };
+2 -6
View File
@@ -1,5 +1,4 @@
import type { import type {
// 系列类型的定义后缀都为 SeriesOption
BarSeriesOption, BarSeriesOption,
GaugeSeriesOption, GaugeSeriesOption,
LineSeriesOption LineSeriesOption
@@ -8,18 +7,16 @@ import { BarChart, GaugeChart, LineChart } from 'echarts/charts';
import type { import type {
DatasetComponentOption, DatasetComponentOption,
GridComponentOption, GridComponentOption,
// 组件类型的定义后缀都为 ComponentOption
TitleComponentOption, TitleComponentOption,
TooltipComponentOption TooltipComponentOption
} from 'echarts/components'; } from 'echarts/components';
import { import {
// 数据集组件
DatasetComponent, DatasetComponent,
GridComponent, GridComponent,
LegendComponent, LegendComponent,
TitleComponent, TitleComponent,
TooltipComponent, TooltipComponent,
// 内置数据转换器组件 (filter, sort) // (filter, sort)
TransformComponent TransformComponent
} from 'echarts/components'; } from 'echarts/components';
import type { ComposeOption } from 'echarts/core'; import type { ComposeOption } from 'echarts/core';
@@ -27,7 +24,6 @@ import * as echarts from 'echarts/core';
import { LabelLayout, UniversalTransition } from 'echarts/features'; import { LabelLayout, UniversalTransition } from 'echarts/features';
import { CanvasRenderer } from 'echarts/renderers'; import { CanvasRenderer } from 'echarts/renderers';
// 通过 ComposeOption 来组合出一个只有必须组件和图表的 Option 类型
type ECOption = ComposeOption< type ECOption = ComposeOption<
| BarSeriesOption | BarSeriesOption
| LineSeriesOption | LineSeriesOption
@@ -38,7 +34,7 @@ type ECOption = ComposeOption<
| GaugeSeriesOption | GaugeSeriesOption
>; >;
// 注册必须的组件 // register components and charts
echarts.use([ echarts.use([
LegendComponent, LegendComponent,
TitleComponent, TitleComponent,
+9 -10
View File
@@ -49,16 +49,15 @@ export default function useOverlayScroller(options?: any) {
scrollEventElement.current = scrollEventElement.current =
instanceRef.current?.elements()?.scrollEventElement; instanceRef.current?.elements()?.scrollEventElement;
const throttledScroll = React.useMemo( const throttledScroll = React.useCallback(
() => throttle(() => {
throttle(() => { scrollEventElement.current?.scrollTo?.({
scrollEventElement.current?.scrollTo?.({ top: scrollEventElement.current.scrollHeight,
top: scrollEventElement.current.scrollHeight, behavior: 'smooth'
behavior: 'smooth' });
}); instanceRef.current?.update?.();
instanceRef.current?.update?.(); }, 100),
}, 300), [(scrollEventElement.current, instanceRef.current)]
[scrollEventElement.current, instanceRef.current]
); );
const scrollauto = React.useCallback(() => { const scrollauto = React.useCallback(() => {
@@ -37,78 +37,6 @@ const TypeKeyMap = {
} }
}; };
const option = {
title: {
text: ''
},
legend: {
itemWidth: 8,
itemHeight: 8,
data: []
},
grid: {
left: 0,
right: 20,
bottom: 20,
containLabel: true
},
tooltip: {
trigger: 'axis',
formatter(params: any) {
let result = `<span class="tooltip-x-name">${params[0].axisValue}</span>`;
params.forEach((item: any) => {
result += `<span class="tooltip-item">
<span class="tooltip-item-name">
<span style="display:inline-block;margin-right:5px;border-radius:8px;width:8px;height:8px;background-color:${item.color};"></span>
<span class="tooltip-title">${item.seriesName}</span>:
</span>
<span class="tooltip-value">${item.data.value}</span>
</span>`;
});
return `<div class="tooltip-wrapper">${result}</div>`;
}
},
xAxis: {
type: 'category',
boundaryGap: true,
axisTick: {
show: true,
lineStyle: {
color: chartColorMap.tickLineColor
}
},
axisLabel: {
color: chartColorMap.axislabelColor,
// fontFamily: 'unset',
fontSize: 12
},
axisLine: {
show: false
},
data: []
},
yAxis: {
max: 100,
min: 0,
splitLine: {
show: true,
lineStyle: {
type: 'dashed'
}
},
axisLabel: {
color: chartColorMap.axislabelColor,
// fontFamily: 'unset',
fontSize: 12
},
axisTick: {
show: false
},
type: 'value'
},
series: []
};
const UtilizationOvertime: React.FC = () => { const UtilizationOvertime: React.FC = () => {
const intl = useIntl(); const intl = useIntl();
const data = useContext(DashboardContext)?.system_load?.history || {}; const data = useContext(DashboardContext)?.system_load?.history || {};
@@ -353,6 +353,7 @@ const MessageInput: React.FC<MessageInputProps> = ({
type="text" type="text"
icon={<ClearOutlined />} icon={<ClearOutlined />}
size="middle" size="middle"
disabled={loading}
onClick={handleClearAll} onClick={handleClearAll}
></Button> ></Button>
</Tooltip> </Tooltip>
@@ -217,7 +217,6 @@ const ModelItem: React.FC<ModelItemProps> = forwardRef(
}; };
const handleApplyToAllModels = (e: any) => { const handleApplyToAllModels = (e: any) => {
console.log('checkbox change:', e.target.checked);
isApplyToAllModels.current = e.target.checked; isApplyToAllModels.current = e.target.checked;
if (e.target.checked) { if (e.target.checked) {
setGlobalParams({ setGlobalParams({
@@ -334,7 +333,6 @@ const ModelItem: React.FC<ModelItemProps> = forwardRef(
}, [modelList, intl]); }, [modelList, intl]);
useEffect(() => { useEffect(() => {
console.log('globalParams:', globalParams.model, globalParams);
setParams({ setParams({
...params, ...params,
model: model, model: model,
@@ -384,7 +382,7 @@ const ModelItem: React.FC<ModelItemProps> = forwardRef(
<div className="header"> <div className="header">
<span className="title"> <span className="title">
<Select <Select
style={{ minWidth: '120px', maxWidth: '200px' }} style={{ minWidth: '120px', maxWidth: '180px' }}
variant="borderless" variant="borderless"
options={modelFullList} options={modelFullList}
onChange={handleModelChange} onChange={handleModelChange}
@@ -404,7 +402,7 @@ const ModelItem: React.FC<ModelItemProps> = forwardRef(
}} }}
></Select> ></Select>
</span> </span>
<ReferenceParams usage={tokenResult}></ReferenceParams> <ReferenceParams usage={tokenResult} scaleable></ReferenceParams>
<span className="action"> <span className="action">
<Dropdown <Dropdown
menu={{ menu={{
@@ -1,11 +1,13 @@
import { WarningOutlined } from '@ant-design/icons'; import { WarningOutlined } from '@ant-design/icons';
import { useIntl } from '@umijs/max'; import { useIntl } from '@umijs/max';
import { Alert, Space, Tooltip } from 'antd'; import { Alert, Space, Tooltip } from 'antd';
import classNames from 'classnames';
import _ from 'lodash'; import _ from 'lodash';
import '../style/reference-params.less'; import '../style/reference-params.less';
interface ReferenceParamsProps { interface ReferenceParamsProps {
showOutput?: boolean; showOutput?: boolean;
scaleable?: boolean;
usage: { usage: {
error?: boolean; error?: boolean;
errorMessage?: string; errorMessage?: string;
@@ -20,7 +22,7 @@ interface ReferenceParamsProps {
const ReferenceParams = (props: ReferenceParamsProps) => { const ReferenceParams = (props: ReferenceParamsProps) => {
const intl = useIntl(); const intl = useIntl();
const { usage, showOutput = true } = props; const { usage, showOutput = true, scaleable } = props;
if (!usage || _.isEmpty(usage)) { if (!usage || _.isEmpty(usage)) {
return null; return null;
} }
@@ -41,8 +43,16 @@ const ReferenceParams = (props: ReferenceParamsProps) => {
); );
} }
return ( return (
<div className="reference-params"> <div
<span className="usage"> className={classNames('reference-params', {
scaleable: scaleable
})}
>
<span
className={classNames('usage', {
scaleable: scaleable
})}
>
<Tooltip <Tooltip
title={ title={
<Space> <Space>
@@ -65,7 +75,11 @@ const ReferenceParams = (props: ReferenceParamsProps) => {
</span> </span>
{showOutput && ( {showOutput && (
<span className="usage"> <span
className={classNames('usage', {
scaleable: scaleable
})}
>
<Tooltip <Tooltip
title={ title={
<Space> <Space>
@@ -4,6 +4,7 @@
border: 1px solid var(--ant-color-border); border: 1px solid var(--ant-color-border);
border-radius: var(--border-radius-base); border-radius: var(--border-radius-base);
height: 100%; height: 100%;
background-color: var(--color-white-1);
.header { .header {
padding-inline: 2px 16px; padding-inline: 2px 16px;
@@ -6,7 +6,16 @@
color: var(--ant-orange); color: var(--ant-orange);
gap: 20px; gap: 20px;
&.scaleable {
gap: 15px;
}
.usage { .usage {
cursor: pointer; cursor: pointer;
line-height: 16px;
&.scaleable {
transform: scale(0.9);
}
} }
} }