xxxxxxxxxxxxxxxx

用法

 <Chart :type="['Bar']" :dataSet="dataSet" />

Chart 组件

<template>
  <div ref="chartRef" class="chart"></div>
</template>

<script>
import BaseECharts from "@/components/Charts/baseChart";
import _ from "lodash";
export default {
  name: "Chart",
  props: {
    type: {
      type: Array,
      default: () => [],
      required: true,
    },
    dataSet: {
      type: Object,
      default: () => ({
        xAxisData: [],
        seriesData: [],
        seriesName: [],
      }),
    },
    beforeRender: {
      type: Function,
      default: () => {},
    },
  },
  data() {
    return {
      chart: null,
      chartOptions: {},
    };
  },

  watch: {
    dataSet: {
      handler(nVal) {
        setTimeout(() => {
          const dataSet = _.cloneDeep(nVal);
          // dataSetTransformToOptions 将data和 echarts options 关联
          const op = this.chart.dataSetTransformToOptions(dataSet);
          this.chartOptions = this.beforeRender ? this.beforeRender(op) : op;
          this.chart.setOption(op, true);
        });
      },
      deep: true,
    },
  },
  mounted() {
    this.chart = new BaseECharts(this.$refs.chartRef, this.type);
  },
};
</script>

BaseECharts class 实例化图表

import * as echarts from "echarts";
import BaseOptionsManage from "@/components/Charts/baseChartOptionManage";
import { CHART_TYPE_ENUM } from "@/components/Charts/options";

class BaseECharts extends BaseOptionsManage {
    constructor($el, type) {
        super(type);
        let myChart = echarts.getInstanceByDom($el)
            ? echarts.getInstanceByDom($el)
            : echarts.init($el);
        window.addEventListener("resize", function () {
            myChart.resize();
        });
        this.charts = myChart;
        setTimeout(() => myChart.resize());
        setTimeout(() => {
            myChart.setOption(CHART_TYPE_ENUM[_.head(this.type)].baseOptions, true);
        });
    }
    setOption(op) {
        this.charts.setOption(op);
        setTimeout(() => {
            this.charts.resize();
        }, 10);
    }

    getOption() {
        if (!this.charts) {
            return null;
        }
        return this.charts.getOption();
    }
}

export default BaseECharts;

options class

import _ from "lodash";
import { CHART_TYPE_ENUM } from "@/components/Charts/options";
import Utils from "./utils";
class BaseOptionsManage {
  constructor(type) {
    this.type = type;
  }

  mergeDataToOptions(dataSet) {
    const [selfType, ...resetTypes] = this.type;
    const selfChart = _.head(
      Utils.chartGenerator(selfType, true).map((c) => {
        return {
          ...c,
          chart: {
            ...c.chart,
            // 生成指令
            drawCalls: Utils.drawGenerator(
              c.chart.drawCalls,
              dataSet.seriesData.length
            ),
          },
        };
      })
    );

    const charts = Utils.chartGenerator(resetTypes).map((c) => {
      return {
        ...c,
      };
    });
    // 整合 series
    const selfBaseOptions = _.set(selfChart.chart.baseOptions, "series", [
      ...selfChart.chart.baseOptions.series,
      ...charts,
    ]);

    const drawCalls = selfChart.chart.drawCalls;
    //运行指令
    drawCalls.forEach((draw) => {
      const { key, call, type } = draw;
      // 解析指令
      const index = key.match(/\[(.*?)\]/)?.[1] || 0;
      if (key.includes("formatter")) {
        const keyOptions = _.get(selfBaseOptions, key);
        _.set(selfBaseOptions, key, (params) =>
          // 将上下文回传
          call({
            options: keyOptions,
            data: dataSet.seriesData[index],
            dataSet,
            index,
            params,
          })
        );
      } else {
        const keyOptions = _.get(selfBaseOptions, key);
         // 将上下文回传
        _.set(
          selfBaseOptions,
          key,
          call({
            options: keyOptions,
            data: dataSet.seriesData[index],
            dataSet,
            index,
          })
        );
      }
    });
    return selfBaseOptions;
  }

  mergeData(dataSet) {
    return this.mergeDataToOptions(dataSet);
  }

  dataSetTransformToOptions(
    dataSet = {
      xAxisData: [],
      seriesData: [],
      seriesName: [],
    }
  ) {
    const options = this.mergeData(dataSet);

    return options;
  }
}

export default BaseOptionsManage;

bar图定义

import { BaseDrawCalls } from "@/components/Charts/options/draw";
import { thousandSignNumber } from "@/utils/numeral";
import _ from "lodash";
import Utils from "../utils";

const baseOptions = {
  color: ["#74A7FF"],
  tooltip: {
    trigger: "axis",
    padding: 0,
    backgroundColor: "rgba(255,255,255,0.95);",
    axisPointer: {
      type: "line",
      lineStyle: {
        width: "99",
        type: "solid",
        color: {
          type: "linear",
          x: 0,
          y: 0,
          x2: 0,
          y2: 1,
          colorStops: [
            {
              offset: 0,
              color: "rgba(255,255,255,0.1)", // 0% 处的颜色
            },
            {
              offset: 1,
              color: "rgba(152,152,152,0.1)", // 100% 处的颜色
            },
          ],
        },
      },
    },
  },
  legend: {
    itemWidth: 8,
    itemHeight: 8,
    show: true,
    left: 0,
  },
  grid: {
    left: 0,
    right: 0,
    bottom: 0,
    containLabel: true,
    top: 52,
  },
  xAxis: [
    {
      type: "category",
      data: [],
      axisTick: {
        alignWithLabel: true,
        lineStyle: {
          color: "#8c8c8c",
        },
      },
      axisLabel: {
        margin: 13,
        color: "#8c8c8c",
      },
    },
  ],
  yAxis: [
    {
      type: "value",
      axisTick: {
        alignWithLabel: true,
      },
      axisLabel: {
        color: "#8c8c8c",
      },
      splitLine: {
        lineStyle: {
          type: "dashed",
          color: "#F0F0F0",
        },
      },
    },
  ],
  series: [
    {
      type: "bar",
      data: [],
      barWidth: 16,
      splitLine: {
        lineStyle: {
          type: "dashed",
          color: "#74A7FF",
        },
      },
    },
  ],
};
// 指令集
const drawCalls = [
  {
    key: "series[Index].data",
    type: Array,
    call: (context) => {
      return context.data;
    },
  },
  {
    key: "series[Index].name",
    type: Array,
    call: (context) => {
      const { index } = context;
      return context.dataSet.seriesName[index];
    },
  },
  {
    key: "xAxis[0].data",
    call: (context) => {
      return context.dataSet.xAxisData;
    },
  },
  {
    key: "yAxis[Index].min",
    call: (context) => {
      return 0;
    },
  },
  {
    key: "yAxis[Index].interval",
    call: (context) => {
      const [seriesData] = context.dataSet.seriesData;
      const { interval } = Utils.formatAxis([...seriesData]);
      return interval;
    },
  },
  {
    key: "yAxis[Index].max",
    call: (context) => {
      const [seriesData] = context.dataSet.seriesData;
      const { max } = Utils.formatAxis([...seriesData]);
      return max;
    },
  },
  {
    key: "tooltip.formatter",
    call: (context) => {
      const html = context.params.reduce((prev, series) => {
        const { axisValue, color, seriesName, data } = series;
        prev.x = axisValue;
        if (prev.values?.length) {
          prev.values.push({ ...data, seriesName, color });
        } else {
          prev.values = [];
          prev.values.push({ ...data, seriesName, color });
        }
        return prev;
      }, {});
      return `<div class="wly-charts-tooltip-container">
                   <div class="x-axis">${html.x}</div>
                  ${html?.values
                    ?.map(({ value, seriesName, color, unit }) => {
                      const [int, float] = String(value).split(".");
                      return `<div class="row"><span class="circle" style="background-color:${color}"></span> <span class="text">${seriesName}</span><span class="value">${
                        value && float
                          ? `${thousandSignNumber(int)?.value}.${float}`
                          : value
                      }</span> <span class="unit">${unit ? unit : ""}</span>
                    </div>`;
                    }, "")
                    .join("\n")}
                  </div>
                `;
    },
  },
];

export default {
  drawCalls,
  baseOptions,
};

工具库

import _ from "lodash";
import { CHART_TYPE_ENUM } from "@/components/Charts/options";
const formatAxis = (axis) => {
  const absAxis = axis.map((item) => Number(item.value));
  const max = Math.max(...absAxis);
  const min = Math.min(...absAxis);

  if (max <= 5) {
    return {
      max: 5,
      interval: 1,
    };
  }
  const exponent = String(Math.floor(max)).length;
  if (exponent < 3) {
    return {
      max: 100,
      interval: 20,
    };
  }
  if (min < 0) {
    const twoNegativeDigit = String(Math.abs(Math.floor(min))).slice(0, 2);
    const NegativeExponent = String(Math.floor(min)).length;
    const minOfYaxis = 10 ** (NegativeExponent - 3);
    const minNumber = (Number(twoNegativeDigit) + 1) * minOfYaxis;
    const twoDigit = String(Math.floor(max + minNumber)).slice(0, 2);
    const exponent = String(Math.floor(max)).length;
    const maxOfYaxis = 10 ** (exponent - 2);
    const maxNumber =
      (Number(twoDigit) + 1) * maxOfYaxis + (minNumber < 1 ? 5 : minNumber);

    return {
      min: minNumber < 1 ? -5 : -minNumber,
      max:
        (Number(twoDigit) + 1) * maxOfYaxis < 1
          ? 5
          : (Number(twoDigit) + 1) * maxOfYaxis,
      interval: (maxNumber < 1 ? 5 : maxNumber) / 5,
    };
  } else {
    const twoDigit = String(Math.floor(max)).slice(0, 2);
    const exponent = String(Math.floor(max)).length;
    const maxOfYaxis = 10 ** (exponent - 2);

    return {
      max: (Number(twoDigit) + 1) * maxOfYaxis,
      interval: ((Number(twoDigit) + 1) * maxOfYaxis) / 5,
    };
  }
};
// 指令生成
const drawGenerator = (drawCalls, number) => {
  const dcs = _.cloneDeep(drawCalls);
  const result = [];
  while (dcs.length) {
    const item = dcs.pop();
    if (item.key.includes("[Index]")) {
      new Array(number).fill(0).forEach((_, index) => {
        result.push({
          ...item,
          key: `${item.key.replace("[Index]", `[${index}]`)}`,
        });
      });
    } else {
      result.push({
        ...item,
      });
    }
  }
  return result;
};
// 提取series
const chartGenerator = (types, isSelf = false) => {
  if (isSelf) {
    return [
      {
        input: types,
        chart: CHART_TYPE_ENUM[types],
      },
    ];
  } else {
    return types.map((type) => {
      return _.head(CHART_TYPE_ENUM[type].baseOptions.series);
    });
  }
};

export default {
  formatAxis,
  drawGenerator,
  chartGenerator,
};

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值