1、定義chart元件
<template> <div ref="chart"></div> </template> <script> import elementResizeDetector from "element-resize-detector"; import * as echarts from "echarts/core"; import { LineChart, BarChart, PieChart, GraphChart, LinesChart } from "echarts/charts"; import { GridComponent, SingleAxisComponent, TooltipComponent, AxisPointerComponent, TitleComponent, LegendComponent, DataZoomComponent, } from "echarts/components"; import { CanvasRenderer } from "echarts/renderers"; echarts.use([ TitleComponent, TooltipComponent, LegendComponent, SingleAxisComponent, GridComponent, AxisPointerComponent, BarChart, LineChart, PieChart, GraphChart, LinesChart, DataZoomComponent, CanvasRenderer, ]); export default { name: "viChart", props: { options: { type: Object, required: true, }, isClear: { type: Boolean, default: true, }, }, // model: { // prop: "myChart", // event: "setModel", // }, data() { return { myChart: null, }; }, beforeDestroy() { this.dispose(); }, methods: { watchOptions() { this.$watch("options", this.setOption, { deep: true }); }, init() { this.myChart = echarts.init(this.$refs.chart); this.setOption(); // 監聽echart的點選事件,點選元素 this.myChart.on("click", params => { this.$emit("getChartObjOnClick", params, this.myChart); }); // 監聽echart的點選事件,getZr()方法可以監聽到整個畫布的點選事件 this.myChart.getZr().on("click", params => { this.$emit("getChartPanelOnClick", params, this.myChart); }); }, resize() { if (!this.myChart) return; this.myChart.resize(); }, setOption() { if (!this.myChart || Object.keys(this.options).length === 0) return; if (this.isClear) { this.myChart.clear(); } this.myChart.setOption(this.options); }, dispose() { if (!this.myChart) return; this.myChart.dispose(); }, }, mounted() { this.init(); this.watchOptions(); this.erd = elementResizeDetector(); this.erd.listenTo(this.$refs.chart, this.resize); }, beforeDestroy() { this.erd.removeListener(this.$refs.chart); }, }; </script>
2、定義常見echart場景
// 餅狀圖顏色 const colors = ["#5B8FF9", "#5AD8A6", "#5D7092", "#F6BD16", "#E8684A", "#6DC8EC", "#9270CA", "#FF9D4D", "#269A99", "#FF99C3"]; // legend的大小 const itemHeight = 8; const itemWidth = 11; // 餅圖(環形圖,中心顯示名稱和數值,有標籤名和標籤連線) const pieOptionFun = (options = {}) => { const pieOption = { title: { text: ["{name|名稱}", "{value|0}"].join("\n"), top: options.titleTop || "center", left: options.titleLeft || "50%", textAlign: "center", textStyle: options.textStyle || { rich: { value: { color: "#555", fontSize: 20, lineHeight: 24, }, name: { color: "#555", fontSize: 14, lineHeight: 35, }, }, }, }, tooltip: { trigger: "item", confine: true, formatter: "{b}: {c} (佔比{d}%)", }, legend: { type: "scroll", // 設定圖例翻頁 orient: "vertical", right: "0%", icon: "circle", itemHeight, itemWidth, textStyle: { color: "#8C8C8C", rich: { nameCls: { fontWeight: 400, fontSize: 14, padding: [5, 0, 5, 0], width: options.richWidth || 80, }, valueCls: { fontSize: 12, padding: [0, 0, 0, 0], width: options.valueWidth || 40, textAlign: "center", }, }, }, }, grid: { left: "0%", right: "0%", bottom: "0%", top: options.gridTop || "0%", containLabel: true, }, color: colors, series: [ { type: "pie", startAngle: options.seriesStartAngle || 90, radius: options.seriesRadius || ["45%", "65%"], center: options.seriesCenter || ["50%", "50%"], label: { show: false, }, data: [ // { name: "克萊因壺", value: 3.5 }, // { name: "投資最重要的事", value: 2.8 }, // { name: "簡讀中國史", value: 1.7 }, // { name: "你當像鳥飛往你的山", value: 1.4 }, // { name: "表象與本質", value: 0.5 }, // { name: "其它", value: 3.8 } ], }, ], }; return pieOption; }; // 柱狀圖,型別過多需要分頁 const barOptionFun = (options = {}) => { const barOption = { title: { text: "", }, tooltip: { trigger: "axis", axisPointer: { type: "shadow", }, formatter: "{b}<br />數量: {c}%", }, legend: { right: "0%", itemHeight, itemWidth, }, xAxis: { type: "category", data: [], // ["Hannah Krause", "Zhao Qian", "Jasmin Krause", "Li Lei", "Karle Neumann", "Adrian Groß", "Mia Neumann"], axisTick: { alignWithLabel: true, }, axisLabel: { interval: 0, // 座標軸刻度標籤的顯示間隔,在類目軸中有效。預設會採用標籤不重疊的策略間隔顯示標籤。可以設定成 0 強制顯示所有標籤。 formatter: (params) => { let newParamsName = params; if (options.xAxisLabelLength) { // 表示是否擷取資料 if (params.length > options.xAxisLabelLength) { newParamsName = `${params.slice(0, options.xAxisLabelLength - 1)}...`; } } return newParamsName; // 將最終的字串返回 }, }, }, yAxis: { type: "value", alignTicks: true, axisLine: { show: true, }, axisLabel: { formatter: "{value}", }, }, grid: { left: "0%", right: "0%", bottom: "10%", top: "10%", containLabel: true, }, color: ["#eecb5f"], series: [ { type: "bar", barMaxWidth: "30", data: [], // [41, 20, 52, 37, 25, 19, 71] }, ], }; return barOption; }; // 折線圖 const lineOptionFun = (options = {}) => { const lineOption = { title: { text: "", }, tooltip: { trigger: "axis", formatter: "", confine: true, }, legend: { top: 0, right: 0, icon: "rect", itemHeight, itemWidth, }, color: options.colors || colors, xAxis: { type: "category", data: [], // data: ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"], axisTick: { alignWithLabel: true, }, axisLabel: { interval: 0, // 座標軸刻度標籤的顯示間隔,在類目軸中有效。預設會採用標籤不重疊的策略間隔顯示標籤。可以設定成 0 強制顯示所有標籤。 color: "#000000", }, }, yAxis: { name: options.yAxisName || "", nameTextStyle: options.nameTextStyle || undefined, type: "value", alignTicks: true, axisLine: { show: options.yAxisAxisLine, // 是否顯示y軸座標軸軸線 }, axisLabel: { color: "#000000" } }, grid: { left: options.gridLeft || "2%", right: "2%", bottom: options.gridBottom || "5px", top: options.gridTop || "10%", containLabel: true, }, series: [ // { // name: "Email", // type: "line", // smooth: true, // data: [20, 132, 101, 134, 90, 230, 110] // }, // { // name: "Union Ads", // type: "line", // smooth: true, // data: [20, 182, 191, 234, 290, 230, 110] // }, ], }; return lineOption; };
3、vue頁面使用
// vue頁面定義 <vi-chart class="echart" :options="weekAlarmOptions" @getChartObjOnClick="getChartObjOnClickWeek"></vi-chart> // options渲染 // deepCopy()方法,表示深度複製 this.weekAlarmOptions = deepCopy( barOption4Fun({ xAxisLabelLength: 3, colors: ["#2277CC", "#9270CA", "#269A99", "#3300f9", "#6DC8EC"], gridBottom: "1%", }) ); // echart的點選事件獲取 getChartObjOnClickWeek(params) { const xxx= params.xxx; const query = { xxx }; this.$router.push({ path: "/xxx", query }); },