feat(hooks): add use-echarts

This commit is contained in:
Soybean 2024-01-19 02:17:17 +08:00
parent b43c925696
commit 726abe4208
3 changed files with 205 additions and 0 deletions

View File

@ -51,6 +51,7 @@
"@vueuse/core": "10.7.2", "@vueuse/core": "10.7.2",
"clipboard": "2.0.11", "clipboard": "2.0.11",
"dayjs": "1.11.10", "dayjs": "1.11.10",
"echarts": "^5.4.3",
"lodash-es": "4.17.21", "lodash-es": "4.17.21",
"naive-ui": "2.37.3", "naive-ui": "2.37.3",
"nprogress": "0.2.0", "nprogress": "0.2.0",

View File

@ -38,6 +38,9 @@ importers:
dayjs: dayjs:
specifier: 1.11.10 specifier: 1.11.10
version: 1.11.10 version: 1.11.10
echarts:
specifier: ^5.4.3
version: 5.4.3
lodash-es: lodash-es:
specifier: 4.17.21 specifier: 4.17.21
version: 4.17.21 version: 4.17.21
@ -3541,6 +3544,13 @@ packages:
resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==} resolution: {integrity: sha512-I88TYZWc9XiYHRQ4/3c5rjjfgkjhLyW2luGIheGERbNQ6OY7yTybanSpDXZa8y7VUP9YmDcYa+eyq4ca7iLqWA==}
dev: true dev: true
/echarts@5.4.3:
resolution: {integrity: sha512-mYKxLxhzy6zyTi/FaEbJMOZU1ULGEQHaeIeuMR5L+JnJTpz+YR03mnnpBhbR4+UYJAgiXgpyTVLffPAjOTLkZA==}
dependencies:
tslib: 2.3.0
zrender: 5.4.4
dev: false
/electron-to-chromium@1.4.637: /electron-to-chromium@1.4.637:
resolution: {integrity: sha512-G7j3UCOukFtxVO1vWrPQUoDk3kL70mtvjc/DC/k2o7lE0wAdq+Vwp1ipagOow+BH0uVztFysLWbkM/RTIrbK3w==} resolution: {integrity: sha512-G7j3UCOukFtxVO1vWrPQUoDk3kL70mtvjc/DC/k2o7lE0wAdq+Vwp1ipagOow+BH0uVztFysLWbkM/RTIrbK3w==}
dev: true dev: true
@ -7979,6 +7989,10 @@ packages:
typescript: 5.3.3 typescript: 5.3.3
dev: true dev: true
/tslib@2.3.0:
resolution: {integrity: sha512-N82ooyxVNm6h1riLCoyS9e3fuJ3AMG2zIZs2Gd1ATcSFjSA23Q0fzjjZeh0jbJvWVDZ0cJT8yaNNaaXHzueNjg==}
dev: false
/tslib@2.6.2: /tslib@2.6.2:
resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==} resolution: {integrity: sha512-AEYxH93jGFPn/a2iVAwW87VuUIkR1FVUKB77NwMF7nBTDkDrrT/Hpt/IrCJ0QXhW27jTBDcf5ZY7w6RiqTMw2Q==}
dev: true dev: true
@ -8855,3 +8869,9 @@ packages:
resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==} resolution: {integrity: sha512-rVksvsnNCdJ/ohGc6xgPwyN8eheCxsiLM8mxuE/t/mOVqJewPuO1miLpTHQiRgTKCLexL4MeAFVagts7HmNZ2Q==}
engines: {node: '>=10'} engines: {node: '>=10'}
dev: true dev: true
/zrender@5.4.4:
resolution: {integrity: sha512-0VxCNJ7AGOMCWeHVyTrGzUgrK4asT4ml9PEkeGirAkKNYXYzoPJCLvmyfdoOXcjTHPs10OZVMfD1Rwg16AZyYw==}
dependencies:
tslib: 2.3.0
dev: false

View File

@ -0,0 +1,184 @@
import { effectScope, nextTick, onScopeDispose, ref, watch } from 'vue';
import type { ComputedRef, Ref } from 'vue';
import * as echarts from 'echarts/core';
import { BarChart, GaugeChart, LineChart, PictorialBarChart, PieChart, RadarChart, ScatterChart } from 'echarts/charts';
import type {
BarSeriesOption,
GaugeSeriesOption,
LineSeriesOption,
PictorialBarSeriesOption,
PieSeriesOption,
RadarSeriesOption,
ScatterSeriesOption
} from 'echarts/charts';
import {
DatasetComponent,
GridComponent,
LegendComponent,
TitleComponent,
ToolboxComponent,
TooltipComponent,
TransformComponent
} from 'echarts/components';
import type {
DatasetComponentOption,
GridComponentOption,
LegendComponentOption,
TitleComponentOption,
ToolboxComponentOption,
TooltipComponentOption
} from 'echarts/components';
import { LabelLayout, UniversalTransition } from 'echarts/features';
import { CanvasRenderer } from 'echarts/renderers';
import { useElementSize } from '@vueuse/core';
export type ECOption = echarts.ComposeOption<
| BarSeriesOption
| LineSeriesOption
| PieSeriesOption
| ScatterSeriesOption
| PictorialBarSeriesOption
| RadarSeriesOption
| GaugeSeriesOption
| TitleComponentOption
| LegendComponentOption
| TooltipComponentOption
| GridComponentOption
| ToolboxComponentOption
| DatasetComponentOption
>;
echarts.use([
TitleComponent,
LegendComponent,
TooltipComponent,
GridComponent,
DatasetComponent,
TransformComponent,
ToolboxComponent,
BarChart,
LineChart,
PieChart,
ScatterChart,
PictorialBarChart,
RadarChart,
GaugeChart,
LabelLayout,
UniversalTransition,
CanvasRenderer
]);
interface ChartHooks {
onRender?: (chart: echarts.ECharts) => void | Promise<void>;
onDestroy?: (chart: echarts.ECharts) => void | Promise<void>;
}
/**
* use echarts
*
* @param options echarts options
* @param darkMode dark mode
*/
export function useEcharts(options: ECOption, darkMode: Ref<boolean> | ComputedRef<boolean>, hooks?: ChartHooks) {
const scope = effectScope();
const domRef = ref<HTMLElement | null>(null);
const initialSize = { width: 0, height: 0 };
const { width, height } = useElementSize(domRef, initialSize);
let chart: echarts.ECharts | null = null;
function canRender() {
return initialSize.width > 0 && initialSize.height > 0;
}
function isRendered() {
return Boolean(domRef.value && chart);
}
function setOptions(opts: ECOption) {
if (isRendered()) {
chart?.clear();
chart?.setOption({ ...opts, backgroundColor: 'transparent' });
}
}
async function render() {
if (domRef.value) {
const chartTheme = darkMode.value ? 'dark' : 'light';
await nextTick();
chart = echarts.init(domRef.value, chartTheme);
setOptions(options);
await hooks?.onRender?.(chart);
}
}
function resize() {
chart?.resize();
}
async function destroy() {
if (!chart) return;
await hooks?.onDestroy?.(chart);
chart?.dispose();
chart = null;
}
async function changeTheme() {
await destroy();
await render();
}
/**
* render chart by size
*
* @param w
* @param h
*/
async function renderChartBySize(w: number, h: number) {
initialSize.width = w;
initialSize.height = h;
// size is abnormal, destroy chart
if (!canRender()) {
await destroy();
return;
}
// render chart
if (!isRendered()) {
await render();
return;
}
// resize chart
resize();
}
scope.run(() => {
watch([width, height], ([newWidth, newHeight]) => {
renderChartBySize(newWidth, newHeight);
});
watch(darkMode, () => {
changeTheme();
});
});
onScopeDispose(() => {
destroy();
scope.stop();
});
return {
domRef,
setOptions
};
}