<template>
<div ref="chartDom" class="chart-dom"></div>
</template>
<script name="MyChart" lang="ts" setup>
import {
ref,
computed,
watch,
onMounted,
onBeforeUnmount,
PropType,
nextTick,
} from "vue";
import * as ECharts from "echarts";
import { debounce } from "lodash";
import {
baseColorArr,
chartDataType,
chartOptionsType,
chartSupportType,
chartDataItemType,
getLineBarBaseOptions,
getLineSeriesOptions,
getBarSeriesOptions,
config,
} from "./config";
const props = defineProps({
color: {
type: Array as PropType<string[]>,
default: () => {
return baseColorArr;
},
},
// 超过该数字时显示滚动条
showZoomLimit: {
type: Number,
default: 7,
},
// 坐标轴是否两边留白
isBoundaryGap: {
type: Boolean,
default: false,
},
baseOptions: {
type: Object as PropType<chartOptionsType>,
default: () => {
return {};
},
},
data: {
type: Array as PropType<chartDataType[]>,
require: true,
},
});
const emits = defineEmits(["chart-click"]);
const initSeriesData = () => {
if (props?.data?.length) {
getXAxisDataArr();
const tempSeriesArr = props?.data.map(
(item: chartDataType, index: number) => {
const chartOptions = getSeriesItemOptions(item, index);
return {
name: item.name,
data: getValueArr(item.data, item?.valueKey),
type: item.type,
...chartOptions,
};
}
);
const tempLegendDataArr = props?.data.map(
(item: chartDataType) => item.name
);
legendDataArr.value = tempLegendDataArr;
seriesArr.value = tempSeriesArr;
}
};
const getXAxisDataArr = () => {
const labelName = props?.data?.[0]?.labelKey || config.labelKey;
const xDataArr = props?.data?.[0]?.data.map((item) => item[labelName]);
dataArr.value = xDataArr as string[];
};
const callbackMap = {
line: getLineSeriesOptions,
bar: getBarSeriesOptions,
};
const getSeriesItemDefaultOptions = (type: chartSupportType = "line") => {
return callbackMap[type];
};
const getChartBaseOptions = () => {
return getLineBarBaseOptions;
};
const getSeriesItemOptions = (chartItem: chartDataType, index = 0) => {
const cb = getSeriesItemDefaultOptions(chartItem.type);
const defaultOptions = cb(index);
if (chartItem?.options) {
const mergeOptions = Object.assign({}, defaultOptions, chartItem?.options);
return mergeOptions;
} else {
return defaultOptions;
}
};
const getBaseChartOptions = () => {
const cb = getChartBaseOptions();
const baseOptions = cb(dataArr.value.length, props.showZoomLimit);
if (props?.baseOptions) {
const mergeOptions = Object.assign({}, baseOptions, props?.baseOptions);
return mergeOptions;
} else {
return baseOptions;
}
};
const getValueArr = (arr: chartDataItemType[], valueKey?: string) => {
const keyName = valueKey ? valueKey : config.valueKey;
return arr.map((item) => Number(item[keyName]));
};
const resizeHandler = () => {
chartExample.resize();
};
const resizeHandlerOrigin = debounce(resizeHandler, 300);
const dataArr = ref<any[]>([]);
const seriesArr = ref<any[]>([]);
const legendDataArr = ref<string[]>([]);
const getOptions = computed(() => {
const baseOptions = getBaseChartOptions();
const options = {
color: props.color,
...baseOptions,
legend: {
data: legendDataArr.value,
},
xAxis: {
type: "category",
data: dataArr.value,
boundaryGap: props.isBoundaryGap,
axisTick: {
alignWithLabel: true,
},
},
series: seriesArr.value,
};
return options;
});
watch(
() => props.data,
() => {
init();
},
{
deep: true,
}
);
const chartDom = ref();
let chartExample: any = null;
const initChart = () => {
if (chartExample) {
// 若存在图表实例,则先执行销毁操作
chartExample.dispose();
}
nextTick(() => {
chartExample = ECharts.init(chartDom.value);
const options = getOptions.value;
chartExample.setOption(options, true);
initResizerListener();
initChartEvent();
});
};
const initResizerListener = () => {
window.removeEventListener("resize", resizeHandlerOrigin);
window.addEventListener("resize", resizeHandlerOrigin);
};
const initChartEvent = () => {
cancelClickEvent();
chartExample.on("click", (params) => {
emits("chart-click", params);
});
};
const cancelClickEvent = () => {
chartExample.off("click");
};
const init = () => {
initSeriesData();
initChart();
};
onMounted(() => {
init();
});
onBeforeUnmount(() => {
cancelClickEvent();
window.removeEventListener("resize", resizeHandlerOrigin);
chartExample.dispose();
});
</script>
<style lang="scss" scoped>
.chart-dom {
height: 300px;
}
</style>
没有合适的资源?快使用搜索试试~ 我知道了~
资源推荐
资源详情
资源评论
收起资源包目录
echarts.zip (2个子文件)
echarts
config.ts 3KB
index.vue 5KB
共 2 条
- 1
资源评论
夏天爱劳动
- 粉丝: 19
- 资源: 2
上传资源 快速赚钱
- 我的内容管理 展开
- 我的资源 快来上传第一个资源
- 我的收益 登录查看自己的收益
- 我的积分 登录查看自己的积分
- 我的C币 登录后查看C币余额
- 我的收藏
- 我的下载
- 下载帮助
安全验证
文档复制为VIP权益,开通VIP直接复制
信息提交成功