echart中国地图绘制,并在对应的省份上添加柱状图

2,653 阅读1分钟

啊,这是一个美好的一天,这一天我也不知道我要干啥。

最终结果

<template>
  <div id="chart" style="width: 100%; height: 100%"></div>
</template>
<script>
import * as echarts from "echarts";
import "./china";
import resize from "@/utils/mixins/resize";

export default {
  name: "chinaEchart",
  mixins: [resize],
  props: {
    data: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      chart: null,
      dataList: [],
      chinaJson: [], //引入的地图数据
    };
  },
  watch: {
    data(val) {
      this.setOptions(val);
    },
  },
  mounted() {
    this.chinaJson = echarts.getMap("china")?.geoJSON?.features;
    console.log(this.chinaJson);
    this.dataList = [
      // { name: "南海诸岛", value: 0 },
      { name: "北京", value: this.randomValue() },
      { name: "天津", value: this.randomValue() },
      { name: "上海", value: this.randomValue() },
      { name: "重庆", value: this.randomValue() },
      { name: "河北", value: this.randomValue() },
      { name: "河南", value: this.randomValue() },
      { name: "云南", value: this.randomValue() },
      { name: "辽宁", value: this.randomValue() },
      { name: "黑龙江", value: this.randomValue() },
      { name: "湖南", value: this.randomValue() },
      { name: "安徽", value: this.randomValue() },
      { name: "山东", value: this.randomValue() },
      { name: "新疆", value: this.randomValue() },
      { name: "江苏", value: this.randomValue() },
      { name: "浙江", value: this.randomValue() },
      { name: "江西", value: this.randomValue() },
      { name: "湖北", value: this.randomValue() },
      { name: "广西", value: this.randomValue() },
      { name: "甘肃", value: this.randomValue() },
      { name: "山西", value: this.randomValue() },
      { name: "内蒙古", value: this.randomValue() },
      { name: "陕西", value: this.randomValue() },
      { name: "吉林", value: this.randomValue() },
      { name: "福建", value: this.randomValue() },
      { name: "贵州", value: this.randomValue() },
      { name: "广东", value: this.randomValue() },
      { name: "青海", value: this.randomValue() },
      { name: "西藏", value: this.randomValue() },
      { name: "四川", value: this.randomValue() },
      { name: "宁夏", value: this.randomValue() },
      { name: "海南", value: this.randomValue() },
      { name: "台湾", value: this.randomValue() },
      { name: "香港", value: this.randomValue() },
      { name: "澳门", value: this.randomValue() },
    ];
    this.$nextTick((_) => {
      this.initChart();
      this.renderEachArea();
    });
  },
  beforeDestroy() {
    if (!this.chart) {
      return;
    }
    this.chart.dispose();
    this.chart = null;
  },
  methods: {
    randomValue() {
      return Math.round(Math.random() * 1000);
    },
    initChart() {
      this.chart = echarts.init(this.$el);
      this.setOptions(this.data);
    },
    setOptions(data = []) {
      let option = {
        // tooltip: {
        //   formatter: function (params, ticket, callback) {
        //     if (!params.value) {
        //       params.value = "-";
        //     }
        //     return (
        //       params.seriesName + "<br />" + params.name + ":" + params.value
        //     );
        //   }, //数据格式化
        // },
        // visualMap: {
        //   min: 0,
        //   max: 1500,
        //   left: "left",
        //   top: "bottom",
        //   text: ["高", "低"], //取值范围的文字
        //   inRange: {
        //     color: ["#e0ffff", "#006edd"], //取值范围的颜色
        //   },
        //   show: true, //图注
        // },
        // 地图背景颜色
        backgroundColor: new echarts.graphic.RadialGradient(0.5, 0.5, 0.4, [
          {
            offset: 0,
            color: "#4b5769",
          },
          {
            offset: 1,
            color: "#404a59",
          },
        ]),
        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, 0.2)",
              areaColor: "#55C3FC", //地图块颜色
            },
            emphasis: {
              areaColor: "#ff4536", //鼠标选择区域颜色
              shadowOffsetX: 0,
              shadowOffsetY: 0,
              shadowBlur: 20,
              borderWidth: 0,
              shadowColor: "rgba(0, 0, 0, 0.5)",
            },
          },
          emphasis: {
            disabled: true,
            focus: "self",
          },
          // 在地图中对特定的区域配置样式。
          regions: [
            {
              name: "北京",
              itemStyle: {
                areaColor: "red",
                color: "red",
              },
            },
            {
              name: "江苏",
              itemStyle: {
                areaColor: "skyblue",
              },
            },
          ],
        },
        series: [
          {
            name: "信息量",
            type: "map",
            geoIndex: 0,
            data: this.dataList,
          },
        ],
      };
      this.chart.setOption(option);
      this.chart.on("click", (param) => {
        console.log(param);
        alert(param.name);
        // this.$router.push("/home/importData");
      });
    },
    renderEachArea() {
      // 测试echartsInstance. convertToPixel方法
      // https://echarts.apache.org/zh/api.html#echartsInstance.convertToPixel
      // let a = this.chart.convertToPixel("geo", [128.3324, 89.5344]);
      // console.log(a);

      const areaOption = {
        xAxis: [],
        yAxis: [],
        grid: [],
        series: [],
        tooltip: {
          trigger: "axis",
          axisPointer: {
            type: "shadow",
          },
        },
        color: ["#ff4565", "#56844f"],
      };

      this.dataList.forEach((item, idx) => {
        let city = this.chinaJson.find(
          (val) => val?.properties?.name == item.name
        );
        // console.log(city);
        // 依据城市地图坐标(经纬度)获取在echart图上的偏移量(定位)
        let EcPxy = this.chart.convertToPixel(
          "geo",
          city?.properties?.cp || []
        );
        // console.log(EcPxy);
        //基础echart同时绘制多个数据配置
        areaOption.xAxis.push({
          id: idx, // 组件id,在配置中引用标识
          gridIndex: idx, // x轴所在的grid的索引
          type: "category", // 坐标轴类型
          name: item.name, // 坐标轴名称
          nameLocation: "middle",
          data: [item.name],
          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.value], // 柱子数据
            z: 100,
          },
          {
            name: "二号",
            type: "bar", // 柱状图
            xAxisId: idx, // 使用的x轴的id
            yAxisId: idx, // 使用的y轴的id
            barGap: 0, // 柱间距离
            barCategoryGap: 0, // 同一系列的柱间距离
            data: [50], // 柱子数据
            z: 100,
          }
        );
      });

      console.log(areaOption);
      // 应用配置
      this.chart.setOption(areaOption);
    },
  },
};
</script>

我的解决问题流程

  • 会使用搜索引擎
  • 使用过echart
  • 知道echart的文档在哪里
  • 掘金是世界上最棒的网站!

知道要做的项目要用

  • vue项目
  • 本人原来绘制地图使用的是高德地图api,但是组长告诉我原来差不多的项目使用的是echart。

查看echart实例

  • 去echart官方的实例中去找地图,最后找到了一个美国的地图绘制的东西。
  • 细看,拷贝下来。发现运行不了。那我细看个勾八。

百度关键字搜索

  • 搜索内容:echart地图绘制
  • 当然会找到了,但是他没贴图,我还是不确定。所以老子不去试。

掘金永远的神

开始测试

vue项目使用echart,echart封装成组件

<template>
  <div id="chart" style="width: 100%; height: 100%"></div>
</template>
<script>
// "echarts": "^5.3.2"
import * as echarts from "echarts";
// vue-admin项目中抓取的大小可以变化
import resize from "@/utils/mixins/resize";

export default {
  name: "chinaEchart",
  mixins: [resize],
  props: {
    data: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      chart: null,
      dataList: []
    };
  },
  watch: {
    data(val) {
      this.setOptions(val);
    },
  },
  mounted() {
    this.$nextTick((_) => {
      this.initChart();
    });
  },
  beforeDestroy() {
    if (!this.chart) {
      return;
    }
    this.chart.dispose();
    this.chart = null;
  },
  methods: {
    randomValue() {
      return Math.round(Math.random() * 1000);
    },
    initChart() {
      this.chart = echarts.init(this.$el);
      this.setOptions(this.data);
    },
    setOptions(data = []) {
      let option = {
        //...数据内容
      };
      this.chart.setOption(option);
    },
  },
};
</script>

绘制中国地图的样式

image.png 代码没测试,但应该可以:

<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";

export default {
  name: "chinaEchart",
  mixins: [resize],
  props: {
    data: {
      type: Array,
      default: () => [],
    },
  },
  data() {
    return {
      chart: null,
      dataList: [],
    };
  },
  watch: {
    data(val) {
      this.setOptions(val);
    },
  },
  mounted() {
    this.dataList = [
      // { name: "南海诸岛", value: 0 },
      { name: "北京", value: this.randomValue() },
      { name: "天津", value: this.randomValue() },
      { name: "上海", value: this.randomValue() },
      { name: "重庆", value: this.randomValue() },
      { name: "河北", value: this.randomValue() },
      { name: "河南", value: this.randomValue() },
      { name: "云南", value: this.randomValue() },
      { name: "辽宁", value: this.randomValue() },
      { name: "黑龙江", value: this.randomValue() },
      { name: "湖南", value: this.randomValue() },
      { name: "安徽", value: this.randomValue() },
      { name: "山东", value: this.randomValue() },
      { name: "新疆", value: this.randomValue() },
      { name: "江苏", value: this.randomValue() },
      { name: "浙江", value: this.randomValue() },
      { name: "江西", value: this.randomValue() },
      { name: "湖北", value: this.randomValue() },
      { name: "广西", value: this.randomValue() },
      { name: "甘肃", value: this.randomValue() },
      { name: "山西", value: this.randomValue() },
      { name: "内蒙古", value: this.randomValue() },
      { name: "陕西", value: this.randomValue() },
      { name: "吉林", value: this.randomValue() },
      { name: "福建", value: this.randomValue() },
      { name: "贵州", value: this.randomValue() },
      { name: "广东", value: this.randomValue() },
      { name: "青海", value: this.randomValue() },
      { name: "西藏", value: this.randomValue() },
      { name: "四川", value: this.randomValue() },
      { name: "宁夏", value: this.randomValue() },
      { name: "海南", value: this.randomValue() },
      { name: "台湾", value: this.randomValue() },
      { name: "香港", value: this.randomValue() },
      { name: "澳门", value: this.randomValue() },
    ];
    this.$nextTick((_) => {
      this.initChart();
    });
  },
  beforeDestroy() {
    if (!this.chart) {
      return;
    }
    this.chart.dispose();
    this.chart = null;
  },
  methods: {
    randomValue() {
      return Math.round(Math.random() * 1000);
    },
    initChart() {
      this.chart = echarts.init(this.$el);
      this.setOptions(this.data);
    },
    setOptions(data = []) {
      let option = {
        tooltip: {
          formatter: function (params, ticket, callback) {
            if (!params.value) {
              params.value = "-";
            }
            return (
              params.seriesName + "<br />" + params.name + ":" + params.value
            );
          }, //数据格式化
        },
        visualMap: {
          min: 0,
          max: 1500,
          left: "left",
          top: "bottom",
          text: ["高", "低"], //取值范围的文字
          inRange: {
            color: ["#e0ffff", "#006edd"], //取值范围的颜色
          },
          show: true, //图注
        },
        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, 0.2)",
              areaColor: "#55C3FC", //地图块颜色
            },
            emphasis: {
              areaColor: "#ff4536", //鼠标选择区域颜色
              shadowOffsetX: 0,
              shadowOffsetY: 0,
              shadowBlur: 20,
              borderWidth: 0,
              shadowColor: "rgba(0, 0, 0, 0.5)",
            },
          },
          
        },
        series: [
          {
            name: "信息量",
            type: "map",
            geoIndex: 0,
            data: this.dataList,
          },
        ],
      };
      this.chart.setOption(option);
      this.chart.on("click", (param) => {
        console.log(param);
        alert(param.name);
        // this.$router.push("/home/importData");
      });
    },  
  },
};
</script>


全部添加过去

代码最上面。修改了一些东西。

image.png

逻辑

绘制地图数据,在地图数据的对应像素点绘制柱状图。(我弄出来才知道的)

难点

  • 地图绘制,可以找到案例。
    • china.js在哪里获取,install后文件夹中自带
    • 地图的有些配置字段只有 v5.3.0才能用
  • 知道获取对应的像素坐标可以在指定位置绘制折线图
    • 使用城市的经纬度可以获取像素坐标this.chart.convertToPixel("geo", [128.3324, 89.5344])
    • 思考:是否可以直接循环多个柱状图,不使用现在的逻辑
    • 问题:宽度100%的情况下,柱状图固定住了。
    • 我去找我的神去了。
<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(val);
    },
  },
  mounted() {
    this.chinaJson = echarts.getMap("china")?.geoJSON?.features;
    this.dataList = [
      // { name: "南海诸岛", value: 0 },
      { name: "北京", value: this.randomValue() },
      { name: "天津", value: this.randomValue() },
      { name: "上海", value: this.randomValue() },
      { name: "重庆", value: this.randomValue() },
      { name: "河北", value: this.randomValue() },
      { name: "河南", value: this.randomValue() },
      { name: "云南", value: this.randomValue() },
      { name: "辽宁", value: this.randomValue() },
      { name: "黑龙江", value: this.randomValue() },
      { name: "湖南", value: this.randomValue() },
      { name: "安徽", value: this.randomValue() },
      { name: "山东", value: this.randomValue() },
      { name: "新疆", value: this.randomValue() },
      { name: "江苏", value: this.randomValue() },
      { name: "浙江", value: this.randomValue() },
      { name: "江西", value: this.randomValue() },
      { name: "湖北", value: this.randomValue() },
      { name: "广西", value: this.randomValue() },
      { name: "甘肃", value: this.randomValue() },
      { name: "山西", value: this.randomValue() },
      { name: "内蒙古", value: this.randomValue() },
      { name: "陕西", value: this.randomValue() },
      { name: "吉林", value: this.randomValue() },
      { name: "福建", value: this.randomValue() },
      { name: "贵州", value: this.randomValue() },
      { name: "广东", value: this.randomValue() },
      { name: "青海", value: this.randomValue() },
      { name: "西藏", value: this.randomValue() },
      { name: "四川", value: this.randomValue() },
      { name: "宁夏", value: this.randomValue() },
      { name: "海南", value: this.randomValue() },
      { name: "台湾", value: this.randomValue() },
      { name: "香港", value: this.randomValue() },
      { name: "澳门", value: this.randomValue() },
    ];
    this.$nextTick(() => {
      this.initChart();
      this.renderEachArea();
      // 窗口变化监听,不用防抖的话有问题
      window.addEventListener(
        "resize",
        _.debounce(() => {
          this.renderEachArea();
        }, 300)
      );
    });
  },
  beforeDestroy() {
    if (!this.chart) {
      return;
    }
    this.chart.dispose();
    this.chart = null;
  },
  methods: {
    randomValue() {
      return Math.round(Math.random() * 1000);
    },
    initChart() {
      this.chart = echarts.init(this.$el);
      this.setOptions(this.data);
    },
    setOptions(data = []) {
      let option = {
        // tooltip: {
        //   formatter: function (params, ticket, callback) {
        //     if (!params.value) {
        //       params.value = "-";
        //     }
        //     return (
        //       params.seriesName + "<br />" + params.name + ":" + params.value
        //     );
        //   }, //数据格式化
        // },
        // visualMap: {
        //   min: 0,
        //   max: 1500,
        //   left: "left",
        //   top: "bottom",
        //   text: ["高", "低"], //取值范围的文字
        //   inRange: {
        //     color: ["#e0ffff", "#006edd"], //取值范围的颜色
        //   },
        //   show: true, //图注
        // },
        // 地图背景颜色
        // backgroundColor: new echarts.graphic.RadialGradient(0.5, 0.5, 0.4, [
        //   {
        //     offset: 0,
        //     color: "#4b5769",
        //   },
        //   {
        //     offset: 1,
        //     color: "#404a59",
        //   },
        // ]),
        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, 0.2)",
              areaColor: "#55C3FC", //地图块颜色
            },
            emphasis: {
              areaColor: "#ff4536", //鼠标选择区域颜色
              shadowOffsetX: 0,
              shadowOffsetY: 0,
              shadowBlur: 20,
              borderWidth: 0,
              shadowColor: "rgba(0, 0, 0, 0.5)",
            },
          },
          emphasis: {
            disabled: true,
            focus: "self",
          },
          // 在地图中对特定的区域配置样式。
          regions: [
            {
              name: "北京",
              itemStyle: {
                areaColor: "red",
                color: "red",
              },
            },
            {
              name: "江苏",
              itemStyle: {
                areaColor: "#ff6655",
              },
            },
          ],
        },
        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() {
      // 测试echartsInstance. convertToPixel方法
      // https://echarts.apache.org/zh/api.html#echartsInstance.convertToPixel
      // let a = this.chart.convertToPixel("geo", [128.3324, 89.5344]);
      // console.log(a);

      const areaOption = {
        xAxis: [],
        yAxis: [],
        grid: [],
        series: [],
        tooltip: {
          trigger: "axis",
          axisPointer: {
            type: "shadow",
          },
        },
        color: ["#ff4565", "#56844f"],
      };

      this.dataList.forEach((item, idx) => {
        let city = this.chinaJson.find(
          (val) => val?.properties?.name == item.name
        );
        // console.log(city);
        // 依据城市地图坐标(经纬度)获取在echart图上的偏移量(定位)
        let EcPxy = this.chart.convertToPixel(
          "geo",
          city?.properties?.cp || []
        );
        // console.log(EcPxy);
        //基础echart同时绘制多个数据配置
        areaOption.xAxis.push({
          id: idx, // 组件id,在配置中引用标识
          gridIndex: idx, // x轴所在的grid的索引
          type: "category", // 坐标轴类型
          name: item.name, // 坐标轴名称
          nameLocation: "middle",
          data: [item.name],
          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.value], // 柱子数据
            z: 100,
          },
          {
            name: "二号",
            type: "bar", // 柱状图
            xAxisId: idx, // 使用的x轴的id
            yAxisId: idx, // 使用的y轴的id
            barGap: 0, // 柱间距离
            barCategoryGap: 0, // 同一系列的柱间距离
            data: [50], // 柱子数据
            z: 100,
          }
        );
      });

      // console.log(areaOption);
      // 应用配置
      this.chart.setOption(areaOption);
    },
  },
};
</script>