echarts在微信小程序绘制地图,并实现点击跳转省地图功能(一)

2,829 阅读4分钟

最近接到一个需求,在微信小程序中展现一个地图,并且实现点击对应省份跳转到省份地图的效果。参阅了很多网络上的教程,感觉都不是很清晰,于是就把我的实现路径记录下来,保证重复可用。

下篇echarts在微信小程序绘制中国地图,并实现点击跳转省地图功能(二) - 掘金 (juejin.cn)

项目地址:gitee.com/huadeng863/…

一、准备工作

1. 准备echats文件

把github中这个文件夹copy到微信小程序中。

GitHub - ecomfe/echarts-for-weixin: Apache ECharts 的微信小程序版本

image.png image.png

2. json文件中引入组件:

{
  "usingComponents": {
    "ec-canvas": "../../ec-canvas/ec-canvas"
 }
}

image.png

3.准备各省市地图

DataV.GeoAtlas地理小工具系列 (aliyun.com)

image.png

访问这个接口,然后复制下页面的所有内容。

找个位置新建个js文件,我这个MapData.js。然后写一个

module.exports = 

粘贴上面复制的内容。记得格式化一下。 image.png

二、地图实现

1. wxml文件:

<view class="container">
  <ec-canvas id="mychart-dom-map" canvas-id="mychart-map" ec="{{ ecMap }}"></ec-canvas>
</view>

2. wxss文件:

.container {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  display: flex;
  flex-direction: column;
  align-items: center;
  justify-content: space-between;
  box-sizing: border-box;
} 
#mychart-dom-map {
  position: relative;
  width: 100%;
  padding-top: 20rpx;
  height: 720rpx;
}

3. 最重要的js文件

// pages/map/map.js
import * as echarts from '../../ec-canvas/echarts.js';
import geoJson from '../functions//mapData.js';

var that;
var click_num = 0;
var click_time;
var click_item;
Page({

  /**
   * 页面的初始数据
   */
  data: {
    ecMap: {
      // 将 lazyLoad 设为 true 后,需要手动初始化图表
      lazyLoad: true
    },
  },

  /**
   * 分布地图
   */
  chinaMap() {
    this.ecComponent.init((canvas, width, height) => {
      let myMap = echarts.init(canvas, null, {
        width: width,
        height: height
      });
      canvas.setChart(myMap);
      echarts.registerMap('china', geoJson); // 绘制地图

      const option = {
        title: {
          text: '寄生虫感染概率'
        },
        tooltip: {
          trigger: 'item',
          backgroundColor: "#FFF",
          padding: [
            10, // 上
            11, // 右
            8, // 下
            10, // 左
          ],
          extraCssText: 'box-shadow: 2px 2px 10px rgba(21, 126, 245, 0.35);',
          textStyle: {
            fontFamily: "'Microsoft YaHei', Arial, 'Avenir', Helvetica, sans-serif",
            color: '#005dff',
            fontSize: 12,
          },
          formatter: `{b} :  感染率:{c}`
        },
        geo: [{
          // 地理坐标系组件
          map: "china",
          roam: true, //支持拖拽缩放
          scaleLimit: {
            //滚轮缩放的极限控制
            min: 1, //缩放最小大小
            max: 6, //缩放最大大小
          },
          aspectScale: 0.8, // 比例
          layoutCenter: ["50%", "30%"], // position位置
          layoutSize: 370, // 地图大小,保证了不超过 370x370 的区域
          label: {
            // 图形上的文本标签
            normal: {
              show: true,
              textStyle: {
                color: "rgba(0, 0, 0, 0.9)",
                fontSize: '8'
              }
            },
            emphasis: { // 高亮时样式
              color: "#333"
            }
          },
          itemStyle: {
            // 图形上的地图区域
            normal: {
              borderColor: "rgba(0,0,0,0.2)",
              areaColor: "#005dff"
            }
          }
        }],
        visualMap: {
          min: 0,
          max: 0.1,
          precision: 4,
          text: ['High', 'Low'],
          realtime: false,
          calculable: true,
          inRange: {
            color: ['lightskyblue', 'yellow', 'orangered']
          }
        },
        series: [{
          type: 'map',
          mapType: 'china',
          geoIndex: 0,
          roam: false, // 鼠标是否可以缩放
          label: {
            normal: {
              show: true
            },
            emphasis: {
              show: true
            }
          },
          data: this.getRandomData(geoJson)
        }]
      };
      myMap.on('click', function (params) {
        // wx.navigateTo({
        //   url: '../mapSub/mapSub?name=' + params.data.name,
        // })
        // todo 手写双击事件
        click_num += 1;

        if (click_item == params.data.name & click_num >= 2 & Date.parse(new Date()) - click_time >= 500) {
          wx.navigateTo({
            url: '../mapSub/mapSub?name=' + params.data.name,
          })
          click_num = 0;
        } else {
          click_item = params.data.name;
          click_time = Date.parse(new Date())
        }

      })
      myMap.setOption(option);
      return myMap
    })
  },


  getRandomData(geoJson) {
    var data = []
    for (let i = 0; i < geoJson.features.length; i++) {
      var itemMap = {}
      itemMap.name = geoJson.features[i].properties.name
      itemMap.value = randomData()
      data.push(itemMap)
    };
    return data;
  },
  /**
   * 生命周期函数--监听页面加载
   */
  onLoad(options) {
    this.ecComponent = this.selectComponent('#mychart-dom-map');
    this.chinaMap();
    that = this;
  },

  /**
   * 生命周期函数--监听页面初次渲染完成
   */
  onReady() {

  },

  /**
   * 生命周期函数--监听页面显示
   */
  onShow() {

  },

  /**
   * 生命周期函数--监听页面隐藏
   */
  onHide() {

  },

  /**
   * 生命周期函数--监听页面卸载
   */
  onUnload() {

  },

  /**
   * 页面相关事件处理函数--监听用户下拉动作
   */
  onPullDownRefresh() {

  },

  /**
   * 页面上拉触底事件的处理函数
   */
  onReachBottom() {

  },

  /**
   * 用户点击右上角分享
   */
  onShareAppMessage() {

  }
})

/**
 * 生成1以内的随机数
 */
function randomData() {
  return Math.round(Math.random() * 0.1 * 10000) / 10000;
}

代码过长,自行下载。其中需要了解的重点有三部分。

3.1. chinaMap函数配置option

image.png

这个option控制了图像的各个属性。配置详情请自行查看option配置官方文档

3.2. 子区域随机取值函数

  getRandomData(geoJson) {
    var data = []
    for (let i = 0; i < geoJson.features.length; i++) {
      var itemMap = {}
      itemMap.name = geoJson.features[i].properties.name
      itemMap.value = randomData()
      data.push(itemMap)
    };
    return data;
  },

因为我这里实现的是一个类似热力图的逻辑,所以需要赋初始化值,要增加一个对各个子子区域随机赋值的逻辑。

网上很多资料都是手动一个个敲,类似下图。如果这样实现全国地图还好,毕竟可以直接copy,但是如果需要实现各个省份地图的话这样赋值就太繁琐了,明显不合理。

image.png

所以我就针对所有的地图逻辑写了一个随机赋值的逻辑,对所有的省市地图均适用

3.3. 单击实现双击逻辑

不知道各位,在微信小程序使用echarts时那个双击事件时有没有出现这个bug,我在实现时,单击事件click测试没问题,但是双击事件dblclick测试怎么也不好用

单击事件直接跳转到省份地图,就把我的tooltip给废掉了,所以这个跳转必须是双击事件。于是就自己自己通过单击事件实现了一个双击事件模拟跳转的逻辑。

var click_num = 0;
var click_time;
var click_item;
chinaMap() {
// ……………………
  myMap.on('click', function (params) {
    click_num += 1;
    if (click_item == params.data.name & click_num >= 2 & Date.parse(new Date()) - click_time >= 500) {
      wx.navigateTo({
        url: '../mapSub/mapSub?name=' + params.data.name,
      })
      click_num = 0;
    } else {
      click_item = params.data.name;
      click_time = Date.parse(new Date())
    }

  })
}

实现逻辑也比较简单,但是也费了我半个钟头才把这个逻辑理顺。以上双击事件模拟确认好使,可放心使用。

4. 实现效果:

image.png