如何快速開始進行echart元件開發

紫藤萝yu發表於2024-08-09

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 });
    },

相關文章