Vue使用echarts渲染地图并根据地区编码展示区域地图

1 功能介绍

  • 默认展示主地图,点击某个省市区根据地区编码展示对应的省市区地图,当匹配不到对应的省市区编码则展示主地图。
  • 根据地理位置坐标加标记。
    最终效果图
  • 点击省市区展示省市区地图
    省市区效果
  • 如果觉得地名位置歪/想让省市区位置在区域中心位置,则需下载地图JSON地图文件进行手动修改(一般名字的位置为省会坐标点),具体修改会在 --- 2.3创建echarts地图 --- 区域写到,因为现在写好像并不清楚到底在写什么。

2 功能实现

2.1 下载所需NPM
npm i axios

npm i echarts
2.2 引入所需配置文件与初始化
2.2.1编码JSON数据项(由于数据量过大,有需要麻烦移步下面文章获取)

省市区编码JSON数据

2.2.2 初始化
<template>
  <div>
    <div id="echatsMap" style="width: 100%; height: 800px"></div>
  </div>
</template>

<script>
import * as echarts from "echarts";
import axios from "axios";
import { cityCode } from "@/components/cityCode.js";
export default {
  name: "echatsMap",
  components: {},
  data() {
    return {
      cityCode: cityCode,
      myChart: "",
      distributionOptions: "",
    };
  },
  mounted() {},
  methods: {},
};
</script>
2.3 创建echarts地图
2.3.1 上面有提到省市区名字可能不在中心位置,可以按以下操作:
  • 点击红框里的下载,就会得到一份本地的JSON文件,2.3.2的代码块为动态获取方式,将本地的JSON地图文件进行修改即可,示例:
      // 此处只举例子
      // 直接在下载的文件里搜甘肃省 --- 这样是默认的
      "properties": {
        "adcode": 620000,
        "name": "甘肃省",
        "center": [
          103.823557,
          36.058039
        ],
        "childrenNum": 14,
        "level": "province",
        "parent": {
          "adcode": 100000
        },
        "subFeatureIndex": 27,
        "acroutes": [
          100000
        ]
      },
      // 在里面加上  用来改变文字展示坐标点
        "cp": [
          103.823557,
          36.058039
        ],
      // 修改后--
      "properties": {
        "adcode": 620000,
        "name": "甘肃省",
        "center": [
          103.823557,
          36.058039
        ],
        "cp": [
          103.823557,
          36.058039
        ],
        "childrenNum": 14,
        "level": "province",
        "parent": {
          "adcode": 100000
        },
        "subFeatureIndex": 27,
        "acroutes": [
          100000
        ]
      },
  • 修改后就不能用动态获取了,需要存放到本地,让其使用本地的文件示例如下(具体改哪来,):
    // 初始化地图数据
    init() {
      // 主地图的JSON文件下载
      let path =  require('../../../../../public/mapJson/china.json');
        echarts.registerMap("china", path );
        this.changeOptions("china");
        this.myChart = echarts.init(document.querySelector("#echatsMap"));
        this.myChart.setOption(this.distributionOptions)
      window.onresize = function () {
        if (this.myChart) this.myChart.resize();
      };
    },
2.3.2 代码实现
<template>
  <div>
    <div id="echatsMap" style="width: 100%; height: 800px"></div>
  </div>
</template>

<script>
import * as echarts from "echarts";
import axios from "axios";
import { cityCode } from "@/components/cityCode.js";
export default {
  name: "echatsMap",
  components: {},
  data() {
    return {
      cityCode: cityCode,
      myChart: "",
      distributionOptions: "",
    };
  },
  mounted() {
    this.$nextTick(() => {
      this.init();
    });
  },
  methods: {
    // 初始化地图数据
    init() {
      // 主地图的JSON文件下载
      let path = `https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json`;
      axios.get(path).then((res) => {
        echarts.registerMap("china", res.data);
        this.changeOptions("china");
        this.myChart = echarts.init(document.querySelector("#echatsMap"));
        this.myChart.setOption(this.distributionOptions)
      });
      window.onresize = function () {
        if (this.myChart) this.myChart.resize();
      };
    },
    // echarts 配置项
    changeOptions(name) {
      // 经纬度数据
      const seriesList = [
        {
          data: [{ value: [106.9, 27.7] }, { value: [105.29, 27.32] }],
        },
      ];
      // 图标
      const series = seriesList.map((v) => {
        return {
          type: "scatter", //配置显示方式为用户自定义
          coordinateSystem: "geo",
          data: v.data,
          // 自定义图标的样式  支持svg与bse64
          symbol: function (params, key) {
            return "image://" + require("@/assets/logo.png");
          },
          symbolSize: 16,
        };
      });

      // options
      this.distributionOptions = {
        tooltip: {
          // 提示框组件
          show: true, // 显示提示框组件
          trigger: "item", // 触发类型
          triggerOn: "mousemove", // 触发条件
          formatter: "名称:{b}<br/>坐标:{c}",
        },
        series, // 数据
        geo: {
          map: name || "china", // 引入地图 省份或者 国家
          layoutCenter: ["50%", "50%"], //设置后left/right/top/bottom等属性无效
          layoutSize: "45%",
          roam: true, //开启鼠标缩放
          zoom: 2,
          label: {
            normal: {
              //静态的时候展示样式
              show: true, //是否显示地图省份得名称
              textStyle: {
                color: "#fff",
                fontSize: 10,
                fontFamily: "Arial",
              },
            },
            emphasis: {
              // 高亮状态下的样式
              //动态展示的样式
              color: "#fff",
            },
          },
          itemStyle: {
            // 地图区域的多边形 图形样式。
            normal: {
              borderColor: "#fff", // 边框颜色
              areaColor: "#1c2f59", //  区域颜色
              // areaColor: { // 使用背景图片
              //   type: "pattern",
              //   image: require("@/assets/texture.jpeg"), // 使用自己本地图片路径
              //   repeat: "repeat", //可选值repeat、no-repeat、repeat-x、repeat-y
              // },
              textStyle: {
                // 文字颜色
                color: "#fff",
              },
              // shadowBlur: 10, // 图形阴影的模糊大小
              // shadowOffsetX: 10, // 阴影水平方向上的偏移距离。
            },
            emphasis: {
              areaColor: "#1c2f59",
              color: "#fff",
            },
          },
          regions: [
            //对不同的区块进行着色
            // {
            //   name: "河南省", //区块名称
            //   itemStyle: {
            //     normal: {
            //       areaColor: "#281fe1",
            //     },
            //   },
            // },
            // {
            //   name: "浙江省", //区块名称
            //   itemStyle: {
            //     normal: {
            //       areaColor: "#193094",
            //     },
            //   },
            // },
          ],
        },
      };
    },
  },
};
</script>
2.4 点击地图省市区展示省市区地图
  • 大概就是点击省市区时根据名称与编码文件去匹配,把匹配到的编码通过外部接口去获取想要的省市区JSON地图数据。再次渲染echarts即可。
  • 注意:如果没匹配到需跳主地图/获取不到此区域的JSON地图数据。
<template>
  <div>
    <div id="echatsMap" style="width: 100%; height: 800px"></div>
  </div>
</template>

<script>
import * as echarts from "echarts";
import axios from "axios";
import { cityCode } from "@/components/cityCode.js";
export default {
  name: "echatsMap",
  components: {},
  data() {
    return {
      cityCode: cityCode,
      myChart: "",
      distributionOptions: "",
    };
  },
  mounted() {
    this.$nextTick(() => {
      this.init();
    });
  },
  methods: {
    // 初始化地图数据
    init() {
      // 主地图的JSON文件下载
      let path = `https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json`;
      axios.get(path).then((res) => {
        echarts.registerMap("china", res.data);
        this.changeOptions("china");
        this.myChart = echarts.init(document.querySelector("#echatsMap"));
        this.myChart.setOption(this.distributionOptions);
        // 点击省份子区域的时候可以切换到省份地图
        this.myChart.on("click", (chinaParam) => {
          // 如果没有下层则展示主地图
          if (!this.cityCode) {
            this.cityCode = cityCode;
            // 100000 主地图
            this.getProvinceMapOpt(100000, "")
            return;
          }
          // 根据点击位置地图名字去跟编码数据匹配
          let code = this.cityCode.find(
            (x) => chinaParam.name.indexOf(x ? x.name : "") !== -1
          );
          // 找到正确的编码   去获取对应的地图数据
          // 将该省市区的下级放入 -- 如果接口支持根据编码查询省市区所有下级子级就不需要这么写
          if (code) {
            this.cityCode = code.city;
            this.getProvinceMapOpt(Number(code.adcode), chinaParam.name);
          } else {
            // 没有对应的编码跳主地图
            this.cityCode = cityCode;
            // 100000 主地图
            this.getProvinceMapOpt(100000, "");
          }
        });
      });
      window.onresize = function () {
        if (this.myChart) this.myChart.resize();
      };
    },
    // 下载/显示各省地图
    getProvinceMapOpt(provinceAlphabet, name) {
      // 根据地区编码获取所在地区的JSON地图
      let path = `https://geo.datav.aliyun.com/areas_v3/bound/${provinceAlphabet}_full.json`;
      if (provinceAlphabet === 100000) {
        path = "/mapJson/china.json";
      }
      axios.get(path).then((res) => {
        // 获取完最新的JSON地图数据后,重新渲染
        echarts.registerMap(name, res.data);
        this.changeOptions(name);
        this.myChart.setOption(this.distributionOptions, true);
      });
    },
    // echarts 配置项
    changeOptions(name) {
      // 经纬度数据  --- 不存在的经纬度不会展示出来
      const seriesList = [
        {
          data: [{ value: [106.9, 27.7] }, { value: [105.29, 27.32] }],
        },
      ];
      // 图标
      const series = seriesList.map((v) => {
        return {
          type: "scatter", //配置显示方式为用户自定义
          coordinateSystem: "geo",
          data: v.data,
          // 自定义图标的样式  支持svg与bse64
          symbol: function (params, key) {
            return "image://" + require("@/assets/logo.png");
          },
          symbolSize: 16,
        };
      });

      // options
      this.distributionOptions = {
        tooltip: {
          // 提示框组件
          show: true, // 显示提示框组件
          trigger: "item", // 触发类型
          triggerOn: "mousemove", // 触发条件
          formatter: "名称:{b}<br/>坐标:{c}",
        },
        series, // 数据
        geo: {
          map: name || "china", // 引入地图 省份或者 国家
          layoutCenter: ["50%", "50%"], //设置后left/right/top/bottom等属性无效
          layoutSize: "45%",
          roam: true, //开启鼠标缩放
          zoom: 2,
          label: {
            normal: {
              //静态的时候展示样式
              show: true, //是否显示地图省份得名称
              textStyle: {
                color: "#fff",
                fontSize: 10,
                fontFamily: "Arial",
              },
            },
            emphasis: {
              // 高亮状态下的样式
              //动态展示的样式
              color: "#fff",
            },
          },
          itemStyle: {
            // 地图区域的多边形 图形样式。
            normal: {
              borderColor: "#fff", // 边框颜色
              areaColor: "#1c2f59", //  区域颜色
              textStyle: {
                // 文字颜色
                color: "#fff",
              },
              // shadowBlur: 10, // 图形阴影的模糊大小
              // shadowOffsetX: 10, // 阴影水平方向上的偏移距离。
            },
            emphasis: {
              areaColor: "#1c2f59",
              color: "#fff",
            },
          },
          regions: [
            //对不同的区块进行着色
            // {
            //   name: "河南省", //区块名称
            //   itemStyle: {
            //     normal: {
            //       areaColor: "#281fe1",
            //     },
            //   },
            // },
            // {
            //   name: "浙江省", //区块名称
            //   itemStyle: {
            //     normal: {
            //       areaColor: "#193094",
            //     },
            //   },
            // },
          ],
        },
      };
    },
  },
};
</script>

3 完整代码

<template>
  <div>
    <div id="echatsMap" style="width: 100%; height: 800px"></div>
  </div>
</template>

<script>
import * as echarts from "echarts";
import axios from "axios";
import { cityCode } from "@/components/cityCode.js";
export default {
  name: "echatsMap",
  components: {},
  data() {
    return {
      cityCode: cityCode,
      myChart: "",
      distributionOptions: "",
    };
  },
  mounted() {
    this.$nextTick(() => {
      this.init();
    });
  },
  methods: {
    // 初始化地图数据
    init() {
      // 主地图的JSON文件下载
      let path = `https://geo.datav.aliyun.com/areas_v3/bound/100000_full.json`;
      axios.get(path).then((res) => {
        echarts.registerMap("china", res.data);
        this.changeOptions("china");
        this.myChart = echarts.init(document.querySelector("#echatsMap"));
        this.myChart.setOption(this.distributionOptions);
        // 点击省份子区域的时候可以切换到省份地图
        this.myChart.on("click", (chinaParam) => {
          // 如果没有下层则展示主地图
          if (!this.cityCode) {
            this.cityCode = cityCode;
            // 100000 主地图
            this.getProvinceMapOpt(100000, "")
            return;
          }
          // 根据点击位置地图名字去跟编码数据匹配
          let code = this.cityCode.find(
            (x) => chinaParam.name.indexOf(x ? x.name : "") !== -1
          );
          // 找到正确的编码   去获取对应的地图数据
          // 将该省市区的下级放入 -- 如果接口支持根据编码查询省市区所有下级子级就不需要这么写
          if (code) {
            this.cityCode = code.city;
            this.getProvinceMapOpt(Number(code.adcode), chinaParam.name);
          } else {
            // 没有对应的编码跳主地图
            this.cityCode = cityCode;
            // 100000 主地图
            this.getProvinceMapOpt(100000, "");
          }
        });
      });
      window.onresize = function () {
        if (this.myChart) this.myChart.resize();
      };
    },
    // 下载/显示各省地图
    getProvinceMapOpt(provinceAlphabet, name) {
      // 根据地区编码获取所在地区的JSON地图
      let path = `https://geo.datav.aliyun.com/areas_v3/bound/${provinceAlphabet}_full.json`;
      if (provinceAlphabet === 100000) {
        path = "/mapJson/china.json";
      }
      axios.get(path).then((res) => {
        // 获取完最新的JSON地图数据后,重新渲染
        echarts.registerMap(name, res.data);
        this.changeOptions(name);
        this.myChart.setOption(this.distributionOptions, true);
      });
    },
    // echarts 配置项
    changeOptions(name) {
      // 经纬度数据  --- 不存在的经纬度不会展示出来
      const seriesList = [
        {
          data: [{ value: [106.9, 27.7] }, { value: [105.29, 27.32] }],
        },
      ];
      // 图标
      const series = seriesList.map((v) => {
        return {
          type: "scatter", //配置显示方式为用户自定义
          coordinateSystem: "geo",
          data: v.data,
          // 自定义图标的样式  支持svg与bse64
          symbol: function (params, key) {
            return "image://" + require("@/assets/logo.png");
          },
          symbolSize: 16,
        };
      });

      // options
      this.distributionOptions = {
        tooltip: {
          // 提示框组件
          show: true, // 显示提示框组件
          trigger: "item", // 触发类型
          triggerOn: "mousemove", // 触发条件
          formatter: "名称:{b}<br/>坐标:{c}",
        },
        series, // 数据
        geo: {
          map: name || "china", // 引入地图 省份或者 国家
          layoutCenter: ["50%", "50%"], //设置后left/right/top/bottom等属性无效
          layoutSize: "45%",
          roam: true, //开启鼠标缩放
          zoom: 2,
          label: {
            normal: {
              //静态的时候展示样式
              show: true, //是否显示地图省份得名称
              textStyle: {
                color: "#fff",
                fontSize: 10,
                fontFamily: "Arial",
              },
            },
            emphasis: {
              // 高亮状态下的样式
              //动态展示的样式
              color: "#fff",
            },
          },
          itemStyle: {
            // 地图区域的多边形 图形样式。
            normal: {
              borderColor: "#fff", // 边框颜色
              areaColor: "#1c2f59", //  区域颜色
              textStyle: {
                // 文字颜色
                color: "#fff",
              },
              // shadowBlur: 10, // 图形阴影的模糊大小
              // shadowOffsetX: 10, // 阴影水平方向上的偏移距离。
            },
            emphasis: {
              areaColor: "#1c2f59",
              color: "#fff",
            },
          },
          regions: [
            //对不同的区块进行着色
            // {
            //   name: "河南省", //区块名称
            //   itemStyle: {
            //     normal: {
            //       areaColor: "#281fe1",
            //     },
            //   },
            // },
            // {
            //   name: "浙江省", //区块名称
            //   itemStyle: {
            //     normal: {
            //       areaColor: "#193094",
            //     },
            //   },
            // },
          ],
        },
      };
    },
  },
};
</script>

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,179评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,229评论 2 380
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,032评论 0 336
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,533评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,531评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,539评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,916评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,574评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,813评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,568评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,654评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,354评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,937评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,918评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,152评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,852评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,378评论 2 342

推荐阅读更多精彩内容