Vue 使用 Apache Echarts 绘制地图(拓展篇)

前言

根据大家的私信、留言,还是决定对地图这块的东西进行拓展讲解一下,希望大家能够真正了解、使用、绘制自己想要的地图效果,让大家彻底弄懂Echarts地图,涉及绘制原理、行政区划、SVG地图、地图打点、线路图、飞线图等内容。开始吧!

gitee: echarts-map

Echarts渲染地图原理

// Echarts 官网案例
$.get('map/china_geo.json', function (chinaJson) {
    echarts.registerMap('china', {geoJSON: geoJson});
    var chart = echarts.init(document.getElementById('main'));
    chart.setOption({
        geo: [{
            map: 'china',
            ...
        }]
    });
});

Echarts 允许我们加载 json 文件(地图渲染文件),进而使用 registerMap 注册地图名称,通过 setOption来渲染地图。因此,地图json文件就是Echarts Map 的核心,可以根据不同的 json 文件渲染出不同效果的地图。(所以,自定义地图也是绘制的图形,生成json文件,供map使用)

Echarts基础地图

我们上一篇文章Vue 使用 Apache Echarts 绘制地图(省市、地区、自定义)中,已经给出了地图渲染数据,根据dataV.数据可视化平台中的中国地图,我们渲染出以下地图:

但是这个南海区域拖的太长了,我们需要处理一下,根据上一节原理,是渲染的json数据太多了。我们目前是axios请求得来,不能直接修改,因此,我们需要下载下来,手动处理。

我们把海南的下地市数据删除,仅剩一个海南省主数据时,得到了下图:

还是剩一条线,因此,它可能是独立的数据了,我们看一下拿到的json数据,

最后一项数据没有表明名称,因此,我们可以删除,

如果Echarts没有提供右侧的南海诸岛的缩略图的话,自已一定一定要补上!不然中国地图不完整!!!

如果Echarts没有提供右侧的南海诸岛的缩略图的话,自已一定一定要补上!不然中国地图不完整!!!

如果Echarts没有提供右侧的南海诸岛的缩略图的话,自已一定一定要补上!不然中国地图不完整!!!

如果,Echarts 没有默认提供该缩略图,我们该如何处理?

使用边界生成器,绘制边界,导出为svg,得到下图:

在定位处理一下,即可得到想要的完整的中国地图。

**温馨提示**

这里说一下,Echarts默认使用 china注册的地图,都会加上南海诸岛缩略图,不论你的JSON文件是什么内容,如下:

甚至!,空的json文件,也能渲染出缩略图!这个问题我找了一上午,所以大家注册名字时,尽量规范取名。

Echarts行政区划

中国区划

中国区划:https://github.com/echarts-maps/echarts-china-misc-js

Echarts官网默认给我们提供了很多类型的地图,包括各种区划,但是提供给我们的是地图JS文件,包装了导出方法,不能直接使用,需要使用 map-maker 工具转换,具体方法我就不再这细说了,可以百度一下 echarts-mapmaker 的使用,我们研究一下源码,看它的实现思路:

gulp.task('华中', function(){
  utils.disolve_internal_borders('./node_modules/echarts-china-provinces-js/echarts-china-provinces-js/henan.js', 'henan.geojson', '河南').then(()=>{
    utils.disolve_internal_borders('./node_modules/echarts-china-provinces-js/echarts-china-provinces-js/hubei.js', 'hubei.geojson', '湖北').then(()=>{    
      utils.disolve_internal_borders('./node_modules/echarts-china-provinces-js/echarts-china-provinces-js/hunan.js', 'hunan.geojson', '湖南').then(()=>{
        maker.merge('hubei.geojson', 'henan.geojson');
        maker.merge('hunan.geojson', 'merged_hubei.geojson');
        maker.makeJs('merged_hunan.geojson', path.join(constants.dist, 'hua_zhong.js'), '华中');
      });
    });
  });
});

核心就是加载区划所属省份的json文件,进行合并,得到区划的json文件,进行地图渲染。

自定义区划

根据上诉原理,我们可以自定义区划了,我们已经有了全国省份的json文件,就是china.json文件里的数据项,实现步骤:

  • 计算名称映射

json文件中 adcode是唯一标识每一个省份的,因此,我们需要获取到省份名称及adcode 的映射文件

  // 生成映射文件
    setDataMap() {
      const data = require("./json/china.json");
      this.map = [];
      data.features.forEach((i) => {
        this.map.push({
          name: i.properties.name,
          adcode: i.properties.adcode,
        });
      });
    },
  • 拿到对应省份的json文件

 // 拿到省份对应的 json 文件
    getGeoJson(list) {
      const adcodeList = [];
      const json = {
        type: "FeatureCollection",
        features: [],
      };
      const data = require("./json/china.json");

      // 先获取 adcode
      list.forEach((item) => {
        adcodeList.push(this.map.find((i) => i.name === item)?.adcode);
      });
      adcodeList.forEach((code) => {
        json.features.push(data.features.find((i) => i.properties.adcode === code));
      });
      // 返回拼凑的json文件
      return json;
    },
  • 这个 name与adcode的转换,大家不要觉得没用,用name也能检索,使用adcode是为了数据库存储唯一ID,作为唯一值时,不推荐使用中文。

  • 渲染返回结果

 mounted() {
    this.setDataMap();

    const qhJson = this.getGeoJson(["广西壮族自治区", "广东省"]);

    echarts.registerMap("mapName", {
      geoJSON: qhJson,
    });

    var chart = echarts.init(this.$refs.map);
    chart.setOption({
      geo: [
        {
          map: "mapName",
        },
      ],
    });
  },

中国的七大区划如下(Echarts官网给出的 preview):

区划

包含的省份

苏皖浙

苏州、安徽、浙江,三省合体

华南

广东、广西、海南、香港、澳门

华南2

广东、广西、海南(海南诸岛)、香港、澳门

华北

内蒙古、河北、山西、北京,天津

华中

河南、湖北、湖南

西北

宁夏、'新疆、青海、陕西、甘肃

西南

四川、云南、贵州、西藏、重庆

我们直接验证一个西北(名称一定以我们 json文件为准哈):

 mounted() {
    this.setDataMap();
    // 宁夏    新疆   青海   陕西   甘肃
    const qhJson = this.getGeoJson(["宁夏回族自治区", "新疆维吾尔自治区", "青海省", "陕西省", "甘肃省"]);

    echarts.registerMap("mapName", {
      geoJSON: qhJson,
    });

    var chart = echarts.init(this.$refs.map);
    chart.setOption({
      geo: [
        {
          map: "mapName",
        },
      ],
    });
  },

我们的实现思路没问题。

取消内部线

我们可以通过外部工具实现这个功能,例如:提取北京市的轮廓 样例中,按照操作执行即可,我就不详细展开了,如果不会的,可以留言,我们再讨论。

单列市

单列市的存在比较特殊,是某些特殊的地市级,需要单独以单元出现在中国地图上,简单来说,我想看 北上广深的经济情况,很明显,深圳不是省份,正常是不能与上广深同时出现的。如何处理呢?

下载单列市的json文件【第一个能看到单列市的层级:意思是你要深圳,你在那一层最先看到它?广东省嘛,因此,下载广东省的json

深圳太小了,我拿新疆的地市做测试,道理是一样的

// 处理单列市
    dlsHandle(adcode = 440300) {
      // 在单列市json中找到单列市的json配置项
      const dlsJson = xjJson.features.find(
        (i) => i.properties.adcode === adcode
      );
      const newJson = chinaJson;
      // json 文件渲染存在先后顺序,先渲染的在图层底,后渲染的在顶层(canvas)
      newJson.features.push(dlsJson);
      return newJson;
    },

上诉,自治州也能在全国地图显示了。这样,就能根据自己的业务,实现单列市的处理了。

原理是:

 {
            "type": "Feature",
            "properties": {
                "adcode": 110000,
                "name": "北京市",
            ....
}
这个是北京市的 json数据
  {
            "type": "Feature",
            "properties": {
                "adcode": 652800,
                "name": "巴音郭楞蒙古自治州",
            ...
}
这个是单列市的json数据,类型都是 Feature 一样的,因此,可以直接添加到 全国json数据。

绘制世界地图

世界各地json文件映射:https://github.com/echarts-maps/echarts-countries-js

世界各地 json文件地址:https://github.com/pissang/starbucks/tree/gh-pages/json

上诉两个地址,就是世界地图的json,直接爬虫下来,汇总处理数据就行了(文件我已经处理好了,放在项目里了)

效果图如下:

自定义地图

掌握了原理之后,你想绘制啥,那不是手到擒来。

自定义地图,多用在绘制非常规地图上,比如,绘制校园建筑人数热力、公园景点旅游热度等这些自定义的。下面还是举例说明一下吧(以上海海洋大学人员分布图为例)

使用 边界生成器绘制地图基础数据

上一篇文章中提到了区域相同导致浮窗都一样,添加了自定义name属性,建议在属性面板中处理,不然导出文件太大,根本处理不了,这样也能在绘制的时候,做合并、裁剪操作,使得绘制更加清晰,数据结构合理。

裁剪:想要两个面是独立的,就需要裁剪

先勾选减数,再勾选裁剪,后勾选被减数

执行完后,只会留下一个面,这个面是剪掉被减数后的

但是这个区域我们是需要的,因此,再绘制一遍

这两个面都是独立的面,导出json,看看效果:

这就是面的处理,已经很详细了,下面我就不细说了。需要注意点我会说一下。

再修饰一下,基本上就能出来了

加载SVG地图

加载SVG地图相对简单,但是我们加载自己的svg图的话,需要每一个 <g> 都有name属性,才可以进行交互。如下:

边界生成器导出为svg,加载svg:

// 该加载svg的方式会报错 
echarts.registerMap("map", {
      svg: require('../public/svg/data.svg'),
    });

    var chart = echarts.init(this.$refs.map);
    chart.setOption({
      geo: [
        {
          map: "map",
        },
      ],
    });

因此,不能直接 require或者 import ,应该使用网络请求:

 mounted() {
    // 这里用请求的形式, 
    axios.get("/svg/data.svg").then((res) => {
      echarts.registerMap("map", {
        svg: res.data,
      });

      var chart = echarts.init(this.$refs.map);
      chart.setOption({
        geo: [
          {
            map: "map",
          },
        ],
      });
    });
  },

得到如下:

但是这样子是没有交互的,就是鼠标放上去,也没有显示名称啥的,因此,需要手动添加 name属性:

这样就行了,我们实现一下官网的飞机选座图:

  1. 边界生成器自定义地图,就可以得到空的页面

  1. 绘制 飞机座位

标记name

导出,并处理<g>的name,配置多选及选中颜色等,

 geo: {
          map: "iceland_svg",
          roam: true,
          selectedMode: "multiple",
          select: {
            itemStyle: {
              color: "green",
            },
          },
        },

就这样,剩下的不可选中,直接判断一下就行了。

地图打点

地图打点,需要svg底图实现,不可以加载 json文件。

按上例,先加载SVG,然后处理打点:

// 添加series配置项,
series: {
          type: "effectScatter",
          coordinateSystem: "geo",
          geoIndex: 0,
          data: [[...positionMap[0].position, 100]],
        },

positionMap 就是点数据坐标,可以通过下方法,快速获取点在svg中的坐标

 myChart.getZr().on("click", function (params) {
        var pixelPoint = [params.offsetX, params.offsetY];
        var dataPoint = myChart.convertFromPixel({ geoIndex: 0 }, pixelPoint);
        // 在 SVG 上点击时,坐标会被打印。
        // 这些坐标可以在 `series.data` 里使用。
        console.log(dataPoint);
      });

地图的打点,还可以做线路图 series type = lines


路径图

用于带有起点和终点信息的线数据的绘制,主要用于地图上的航线,路线的可视化。

连续位置的线段(用于绘制线路图等连续性坐标)

非连续的位置,可以实现飞线图:

名称数据映射

这个问题通常出现在请求后端数据时,返回的数据与渲染地图数据不一致,使用nameMap处理(如官网香港18区人口密度 (2011)

思路就是找到两者数据的id,对名称进行数据映射即可。

总结

其实这些东西都是官网的样例,好好研究官网配置文件,相信大家也可以写出来的。以上就是Echarts地图的拓展,有问题交流呀。

猜你喜欢

转载自blog.csdn.net/weixin_47746452/article/details/129672275