|
|
|
|
@ -0,0 +1,238 @@
|
|
|
|
|
<template>
|
|
|
|
|
<div class="WEcharts" ref="WEchartsRef">
|
|
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
<script setup>
|
|
|
|
|
import * as echarts from 'echarts';
|
|
|
|
|
import { useElementSize, useThrottleFn } from '@vueuse/core';
|
|
|
|
|
import { useTemplateRef, watch, onMounted } from 'vue';
|
|
|
|
|
import { unit, objectMerge, deepClone } from '@/util';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const props = defineProps({
|
|
|
|
|
option: {
|
|
|
|
|
type: Object,
|
|
|
|
|
default: {}
|
|
|
|
|
},
|
|
|
|
|
useDefault: {
|
|
|
|
|
type: Boolean,
|
|
|
|
|
default: true
|
|
|
|
|
},
|
|
|
|
|
colors: {
|
|
|
|
|
type: Array,
|
|
|
|
|
default: ['#e74c3c', '#f39c12', '#2ed573', '#e056fd', '#833471']
|
|
|
|
|
},
|
|
|
|
|
color: {
|
|
|
|
|
type: String,
|
|
|
|
|
default: "#FFFA"
|
|
|
|
|
},
|
|
|
|
|
excludes: {
|
|
|
|
|
type: Array,
|
|
|
|
|
default: ['fontSize']
|
|
|
|
|
},
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const emit = defineEmits(['resize', 'load']);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const root = useTemplateRef('WEchartsRef');
|
|
|
|
|
let chart = null;
|
|
|
|
|
let optionGlobal = null;
|
|
|
|
|
|
|
|
|
|
const { width, height } = useElementSize(root);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const getDefaultOption = () => ({
|
|
|
|
|
|
|
|
|
|
color: props.colors,
|
|
|
|
|
tooltip: {
|
|
|
|
|
trigger: 'axis',
|
|
|
|
|
textStyle: {
|
|
|
|
|
fontSize: '.85em',
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
legend: {
|
|
|
|
|
// data: [],
|
|
|
|
|
top: '1em',
|
|
|
|
|
textStyle: {
|
|
|
|
|
color: props.color,
|
|
|
|
|
fontSize: '.9em',
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
grid: {
|
|
|
|
|
top: '3.5em',
|
|
|
|
|
left: '1em',
|
|
|
|
|
right: '1em',
|
|
|
|
|
bottom: '1em',
|
|
|
|
|
containLabel: true,
|
|
|
|
|
},
|
|
|
|
|
xAxis: {
|
|
|
|
|
type: 'category',
|
|
|
|
|
boundaryGap: false,
|
|
|
|
|
// data: [],
|
|
|
|
|
axisLine: {
|
|
|
|
|
lineStyle: {
|
|
|
|
|
color: props.color
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
axisLabel: {
|
|
|
|
|
color: props.color,
|
|
|
|
|
fontSize: '.8em'
|
|
|
|
|
},
|
|
|
|
|
},
|
|
|
|
|
yAxis: {
|
|
|
|
|
type: 'value',
|
|
|
|
|
axisLine: {
|
|
|
|
|
lineStyle: {
|
|
|
|
|
color: props.color,
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
axisLabel: {
|
|
|
|
|
color: props.color,
|
|
|
|
|
fontSize: '.8em'
|
|
|
|
|
},
|
|
|
|
|
splitLine: {
|
|
|
|
|
show: true,
|
|
|
|
|
lineStyle: {
|
|
|
|
|
color: '#FFF2',
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
// series: []
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
const setPxArray = (array, px) => {
|
|
|
|
|
for (let i = 0; i < array.length; i++) {
|
|
|
|
|
if (Array.isArray(array[i])) {
|
|
|
|
|
setPxArray(array[i], px);
|
|
|
|
|
} else if (typeof array[i] === 'object') {
|
|
|
|
|
setPx(array[i], px);
|
|
|
|
|
} else if (typeof array[i] === 'string') {
|
|
|
|
|
if (/^.*\dem$/.test(array[i])) {
|
|
|
|
|
try {
|
|
|
|
|
array[i] = (parseFloat(array[i]) * px) || 0;
|
|
|
|
|
} catch (e) { }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const setPx = (option, px) => {
|
|
|
|
|
for (let key of Object.keys(option)) {
|
|
|
|
|
if (props.excludes.includes(key)) {
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
|
if (Array.isArray(option[key])) {
|
|
|
|
|
setPxArray(option[key], px);
|
|
|
|
|
} else if (typeof option[key] === 'object') {
|
|
|
|
|
setPx(option[key], px)
|
|
|
|
|
} else if (typeof option[key] === 'string') {
|
|
|
|
|
if (/^.*\dem$/.test(option[key])) {
|
|
|
|
|
try {
|
|
|
|
|
option[key] = (parseFloat(option[key]) * px) || 0;
|
|
|
|
|
} catch (e) { }
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const resize = (px) => {
|
|
|
|
|
if (!chart) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
let option = null;
|
|
|
|
|
if (props.useDefault) {
|
|
|
|
|
option = objectMerge(getDefaultOption(), props.option);
|
|
|
|
|
} else {
|
|
|
|
|
option = deepClone(props.option);
|
|
|
|
|
}
|
|
|
|
|
setPx(option, px);
|
|
|
|
|
try {
|
|
|
|
|
delete option.series;
|
|
|
|
|
delete option.legend.data;
|
|
|
|
|
delete option.xAxis.data;
|
|
|
|
|
delete option.yAxis.data;
|
|
|
|
|
} catch (e) { }
|
|
|
|
|
chart.setOption(option);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
onMounted(async () => {
|
|
|
|
|
chart = echarts.init(root.value, 'light', {
|
|
|
|
|
renderer: 'svg'
|
|
|
|
|
});
|
|
|
|
|
let px = unit.em2px(root, 1);
|
|
|
|
|
resize(px);
|
|
|
|
|
emit('load', { chart, setOption,px});
|
|
|
|
|
})
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const doResize = useThrottleFn(() => {
|
|
|
|
|
if (!chart) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
chart.resize({
|
|
|
|
|
width: width.value, // 强制指定新宽度(默认优先使用容器实际宽度)
|
|
|
|
|
height: height.value, // 强制指定新高度(默认优先使用容器实际高度)
|
|
|
|
|
silent: false, // 是否静默更新(不触发事件)
|
|
|
|
|
});
|
|
|
|
|
let px = unit.em2px(root, 1);
|
|
|
|
|
resize(px);
|
|
|
|
|
emit('resize', { chart, setOption, px });
|
|
|
|
|
}, 500, true);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
watch(() => width.value * 10000 + height.value, doResize);
|
|
|
|
|
|
|
|
|
|
const setTitles = (titiles) => {
|
|
|
|
|
setOption({ legend: { data: titiles } });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const setX = (x) => {
|
|
|
|
|
setOption({ xAxis: { data: x } });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const setY = (y) => {
|
|
|
|
|
setOption({ yAxis: { data: y } });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
const setSeries = (series) => {
|
|
|
|
|
setOption({ series });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
const setOption = (option) => {
|
|
|
|
|
if (!chart) {
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
chart.setOption(option);
|
|
|
|
|
doResize();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
defineExpose({
|
|
|
|
|
chart,
|
|
|
|
|
setOption,
|
|
|
|
|
el: root,
|
|
|
|
|
setTitles,
|
|
|
|
|
setX,
|
|
|
|
|
setY,
|
|
|
|
|
setSeries,
|
|
|
|
|
setData: setSeries
|
|
|
|
|
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
<style lang="scss" scoped>
|
|
|
|
|
@layer {
|
|
|
|
|
.WEcharts {
|
|
|
|
|
width: 100%;
|
|
|
|
|
height: 100%;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
</style>
|