echart地图上柱状图,同高,lenged变化问题。

146 阅读1分钟
<template>
  <div id="chart" style="width: 100%; height: 100%"></div>
</template>
<script>
// "echarts": "^5.3.2",
import * as echarts from "echarts";
// node_modules/echart/js下拉出来
import "./china";
// vue-admin项目中抓取的
import resize from "@/utils/mixins/resize";

const _ = require("lodash");

export default {
  name: "chinaEchart",
  mixins: [resize],
  props: {
    data: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      chart: null,
      dataList: [],
      chinaJson: [], //引入的地图数据
    };
  },
  watch: {
    data(val) {
      this.setOptions();
      this.renderEachArea(val);
    },
  },
  mounted() {
    this.chinaJson = echarts.getMap("china")?.geoJSON?.features;
    this.$nextTick(() => {
      this.initChart();
      this.renderEachArea(this.data);
      // 窗口变化监听,不用防抖的话有问题
      //需要销毁时候取消监听,window为全局数据
      window.addEventListener("resize", this.debounce);
    });
  },
  beforeDestroy() {
    if (!this.chart) {
      return;
    }
    this.chart.dispose();
    this.chart = null;
    // 销毁window['resize']。
    window.removeEventListener("resize", this.debounce);
  },
  methods: {
    // 必须封装函数
    debounce: _.debounce(function () {
      this.renderEachArea(this.data);
    }, 300),
    initChart() {
      this.chart = echarts.init(this.$el);
      this.setOptions(this.data);
    },
    setOptions() {
      let option = {
        geo: {
          map: "china",
          roam: false, //不开启缩放和平移
          zoom: 1.23, //视角缩放比例
          label: {
            normal: {
              show: false,
              fontSize: "10",
              color: "rgba(0,0,0,0.7)",
            },
          },
          itemStyle: {
            normal: {
              borderColor: "rgba(0, 0, 0, .6)",
              areaColor: "#fff", //地图块颜色
            },
            emphasis: {
              areaColor: "#ff4536", //鼠标选择区域颜色
              shadowOffsetX: 0,
              shadowOffsetY: 0,
              shadowBlur: 20,
              borderWidth: 0,
              shadowColor: "rgba(0, 0, 0, 0.5)",
            },
          },
          emphasis: {
            // 不弄成放上去就变颜色的那种
            disabled: true,
            focus: "self",
          },
          // 在地图中对特定的区域配置样式。
        },
        // series: [
        //   {
        //     name: "信息量",
        //     type: "map",
        //     geoIndex: 0,
        //     data: this.dataList,
        //   },
        // ],
      };
      this.chart.setOption(option);
      this.chart.on("click", (param) => {
        console.log(param);
      });

      // 监听地图的拖拽与移动
      // 防抖!
      this.chart.on(
        "geoRoam",
        _.debounce((param) => {
          this.renderEachArea();
        }),
        300
      );
    },
    renderEachArea(data = []) {
      // 测试echartsInstance. convertToPixel方法
      // https://echarts.apache.org/zh/api.html#echartsInstance.convertToPixel
      // let a = this.chart.convertToPixel("geo", [128.3324, 89.5344]);
      // console.log(a);
      // 不是很严谨
      // userCount,schoolCount
      let arr = [];
      let schoolArr = [];
      data.forEach((item) => {
        arr.push(item.userCount, item.schoolCount);
        schoolArr.push(item.schoolCount);
      });
      // 获取所有数据最大值
      let maxData = Math.max(...arr);
      // 获取学院最大值
      let maxSchoolData = Math.max(...schoolArr);
      const areaOption = {
        xAxis: [],
        yAxis: [],
        grid: [],
        series: [],
        legend: {
          icon: "circle",
          width: "80",
          right: "0%",
          bottom: "30%",
          textStyle: {
            color: "#727E8F",
          },
          data: [{ name: "院校数" }, { name: "用户数" }],
        },
        tooltip: {
          trigger: "axis",
          axisPointer: {
            type: "shadow",
          },
          formatter: (params, ticket) => {
            let str = "";
            params.forEach((item, index) => {
              if (index % 4 == 0) {
                str += `${item.axisValueLabel}</br>`;
              }
              if (
                item.seriesName != "占位数字" &&
                item.seriesName != "学院最大值"
              ) {
                str += `<div style="font-size: 14px;color: #727E8F;line-height: 26px;">${item.marker}${item.seriesName}:${item.value}</div>`;
              }
            });
            return str;
          },
        },
        color: ["#ff4565", "#56844f"],
      };

      data.forEach((item, idx) => {
        let city = this.chinaJson.find((val) => val?.id == item.provinceId);
        // console.log(city);
        // 依据城市地图坐标(经纬度)获取在echart图上的偏移量(定位)
        let EcPxy = null;
        if (this.chart) {
          EcPxy = this.chart.convertToPixel("geo", city?.properties?.cp || []);
        }

        // console.log(EcPxy);
        //基础echart同时绘制多个数据配置
        areaOption.xAxis.push({
          id: idx, // 组件id,在配置中引用标识
          gridIndex: idx, // x轴所在的grid的索引
          type: "category", // 坐标轴类型
          nameLocation: "middle",
          data: [item.province],
          nameGap: 3, // 坐标轴名称与轴线之间的距离
          splitLine: {
            // 坐标轴在 grid 区域中的分隔线
            show: false,
          },
          axisTick: {
            // 坐标轴刻度
            show: false,
          },
          axisLabel: {
            // 坐标轴刻度标签
            show: false,
          },
          axisLine: {
            // 坐标轴轴线
            onZero: false,
            lineStyle: {
              color: "#666",
            },
          },
          z: 100,
        });
        areaOption.yAxis.push({
          id: idx, // 组件id,在配置中引用标识
          gridIndex: idx, // x轴所在的grid的索引
          splitLine: {
            // 坐标轴在 grid 区域中的分隔线
            show: false,
          },
          axisTick: {
            // 坐标轴刻度
            show: false,
          },
          axisLabel: {
            // 坐标轴刻度标签
            show: false,
          },
          axisLine: {
            // 坐标轴轴线
            show: false,
            lineStyle: {
              color: "#1C70B6",
            },
          },
          z: 100,
        });
        areaOption.grid.push({
          id: idx, // 组件id,在配置中引用标识
          width: 30, // 组件的宽度
          height: 40, // 组件的高度
          left: EcPxy[0] - 15, // 离容器左侧的距离
          top: EcPxy[1] - 40, // 离容器上侧的距离
          z: 100,
        });
        areaOption.series.push(
          {
            name: "院校数",
            type: "bar", // 柱状图
            xAxisId: idx, // 使用的x轴的id
            yAxisId: idx, // 使用的y轴的id
            barGap: 0, // 柱间距离
            barCategoryGap: 0, // 同一系列的柱间距离
            data: [item.schoolCount], // 柱子数据
            // 渐变色
            itemStyle: {
              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                { offset: 0, color: "#3B76E1" },
                { offset: 1, color: "#7BB6F3" },
              ]),
              borderRadius: [20, 20, 0, 0],
            },
            z: 100,
          },
          {
            name: "占位数字",
            type: "bar", // 柱状图
            xAxisId: idx, // 使用的x轴的id
            yAxisId: idx, // 使用的y轴的id
            barGap: "0", // 柱间距离
            barCategoryGap: 0, // 同一系列的柱间距离
            data: [maxData], // 柱子数据
            barWidth: 1,
            // // 渐变色
            itemStyle: {
              opacity: 0,
              borderRadius: [20, 20, 0, 0],
            },
            z: 100,
          },
          {
            name: "学院最大值",
            type: "bar", // 柱状图
            xAxisId: idx, // 使用的x轴的id
            yAxisId: idx, // 使用的y轴的id
            barGap: "0", // 柱间距离
            barCategoryGap: 0, // 同一系列的柱间距离
            data: [maxSchoolData], // 柱子数据
            barWidth: 1,
            // // 渐变色
            itemStyle: {
              opacity: 0,
              borderRadius: [20, 20, 0, 0],
            },
            z: 100,
          },
          {
            name: "用户数",
            type: "bar", // 柱状图
            xAxisId: idx, // 使用的x轴的id
            yAxisId: idx, // 使用的y轴的id
            barGap: 0, // 柱间距离
            barCategoryGap: 0, // 同一系列的柱间距离
            data: [item.userCount], // 柱子数据
            // 渐变色
            itemStyle: {
              color: new echarts.graphic.LinearGradient(0, 0, 0, 1, [
                { offset: 0, color: "#F56E6E" },
                { offset: 1, color: "#FDADA9" },
              ]),
              borderRadius: [20, 20, 0, 0],
            },
            z: 100,
          }
        );
      });

      // console.log(areaOption);
      // 应用配置
      this.chart.setOption(areaOption);

      this.chart.on("legendselectchanged", (params) => {
        // console.log(params);
        // 取消用户数
        if (!params.selected["用户数"]) {
          // console.log("取消用户数");
          this.chart.dispatchAction({
            type: "legendUnSelect",
            name: "占位数字",
          });
        } else {
          // 选定用户数
          // console.log("选定用户数");
          this.chart.dispatchAction({
            type: "legendSelect",
            name: "占位数字",
          });
        }
      });
    },
  },
};
</script>