【微信小程序+echarts点亮中国地图】微信小程序echarts中国地图点亮功能



0 小程序开发背景

前段时间在上学校的软件开发与实践B课程
因为赶上了工大百年校庆,选择了开发百年工大校庆微信小程序
功能涵盖了校庆官方信息发布、校庆应援点亮地图、校庆活动发布、寻找校友、校友回忆、校庆祝福、校庆捐款、校庆周边等

参考的资料有

在这里想复盘一下校庆应援点亮地图的步骤

使用的百度Echarts地图,参考的模板是中国地图模板


1 下载官方Github项目

  • 进入Echarts for weixin,里面有示例步骤以及示例程序。

  • 为了兼容小程序 CanvasEcharts官方提供了一个小程序的组件,用这种方式可以方便地使用 ECharts

    首先,需要下载本项目。其中,ec-canvas是提供的组件,其他文件是如何使用该组件的示例。ec-canvas 目录下有一个 echarts.js,默认我们会在每次 echarts-for-weixin 项目发版的时候替换成最新版的 ECharts。
    如有必要,可以自行从 ECharts 项目中下载最新发布版,或者从官网自定义构建以减小文件大小。

  • 在创建项目之后,可以将下载的 ecomfe/echarts-for-weixin 项目完全替换新建的项目,然后将修改代码;或者仅拷贝 ec-canvas 目录到新建的项目下,然后做相应的调整。


2 按照Echarts官网的map示例使用

map示例

  1. 其中注意需要引进中国地图数据 mapData.js点击此处下载mapData.js

    在js文件中:
    import geoJson from './mapData.js';

    mapData.js中的内容为中国地图坐标文件:

  2. 绘制地图(在js文件中):

  geo: [
    {
      // 地理坐标系组件
      map: "china",
      roam: false, // 可以缩放和平移
      aspectScale: 0.8, // 比例
      layoutCenter: ["50%", "38%"], // position位置
      layoutSize: 370, // 地图大小,保证了不超过 370x370 的区域
      label: {
        // 图形上的文本标签
        normal: {
          show: true,
          textStyle: {
            color: "#E8E8E8",
            fontSize: '8'
          }
        },
        emphasis: { // 高亮时样式
          color: "#333",
          show: false
        }
      },
      itemStyle: {
        // 图形上的地图区域
        normal: {
          borderColor: "#FFD700",
          areaColor: "#87CEFF"
          //#000000 #87CEFF
        }
      }
    }
  ],
  1. 绘制地图上的各种效果(在js文件中):
 series: [
   {
     name: '散点',
     type: 'scatter',
     coordinateSystem: 'geo',
    // data: convertData(data),
     symbolSize: function(val) {
         return val[2] / 100;
     },
     label: {
         normal: {
             formatter: '{b}',
             position: 'left',
             show: false,
             textStyle: {
               color: "rgba(0, 0, 0, 0.9)",
               fontSize: '8'
             }
         },
         emphasis: {
             show: true,
             textStyle: {
               color: "rgba(0, 0, 0, 0.9)",
               fontSize: '8'
             }
         }
     },
     itemStyle: {
         normal: {
             color: '#FFD700'
         }
     }
 },
 
   {
     type: 'map',
     mapType: 'china',
     geoIndex: 0,
     roam: false, // 鼠标是否可以缩放
     label: {
       normal: {
         show: false,
       },
       emphasis: {
         show: false
       }
     },
     itemStyle: {
       normal: {
           color: '#05C3F9',
           fontSize: '8'
       },
     },
    // data:citydata
 },

 
 {
   name: '气泡点',
   type: 'scatter',
   coordinateSystem: 'geo',
   symbol: 'pin', //气泡
   symbolSize: function(val) {
       var a = (maxSize4Pin - minSize4Pin) / (max - min);
       var b = minSize4Pin - a * min;
       b = maxSize4Pin - a * max;
       return (a * val[2] + b)/3;
   },
   label: {
       normal: {
           show: false,
           textStyle: {
               color: '#fff',
               fontSize: 8,
           }
       },
       formatter: '{@[6]}',
   },
  
   itemStyle: {
       normal: {
           color: '#F62157', //标志颜色
           fontSize: 8,
       }
   },
   //zlevel: 6,
  // data: convertData(citydata.sort(function(a, b) {return b.value - a.value;})),
},

{
   name: 'Top 5',
   type: 'effectScatter',
   coordinateSystem: 'geo',
   //data: convertData(citydata.sort(function(a, b) {return b.value - a.value; }).slice(0, 5)),
   symbolSize: function(val) {
       return val[2]/80;
   },
   showEffectOn: 'render',
   rippleEffect: {
       brushType: 'stroke'
   },
   hoverAnimation: true,
   label: {
       normal: {
           formatter: '{b}',
           position: 'right',
           show: false
       }
   },
  
   endcode:{
     label:2
   },
   itemStyle: {
       normal: {
           color: 'yellow',
           shadowBlur: 10,
           shadowColor: 'yellow'
       }
   },
  // zlevel: 1
}],

读取数据时使用的是微信小程序自带的云数据库

 const db = wx.cloud.database()
  getData:function()
  {
    wx.cloud.callFunction({
      name:"getCity"
    })
    .then(res=>{
      //console.log(res.result.data)
      const citydata=[];
      for(var i=0;i<res.result.data.length;i++){
        citydata.push(res.result.data[i])
     }
     //console.log(citydata)
     for(var i=0;i<citydata.length;i++){
        delete citydata[i]._id;
        delete citydata[i]._openid;
     }
     // console.log(citydata)
  
     // option.yAxis[0].data = note;
      option.series[0].data =  convertData(citydata);
      option.series[1].data = citydata;
      option.series[2].data = convertData(citydata.sort(function(a, b) {return b.value - a.value;}));
      option.series[3].data = convertData(citydata.sort(function(a, b) {return b.value - a.value;}).slice(0, 5));
      if(!myMap){
        this.init_ChartMap();
      }else{
        myMap.clear();
        this.init_ChartMap();
      }
    })
  },

3 点击事件的函数

点击点亮之后,云数据库中该地区的数值+1

  lightHIT:function (){
   var cityAll = ['广东省','湖南省','黑龙江省','山东省','吉林省','辽宁省','内蒙古自治区','天津市','陕西省','山西省','宁夏回族自治区','新疆维吾尔自治区','西藏自治区','青海省','河北省','河南省','安徽省','浙江省','江苏省','上海市','重庆市','江西省','贵州省','海南省','台湾省','云南省','香港特别行政区','澳门特别行政区']
   var cityEasy = ['广东','湖南','黑龙江','山东','吉林','辽宁','内蒙古','天津','陕西','山西','宁夏','新疆','西藏','青海','河北','河南','安徽','浙江','江苏','上海','重庆','江西','贵州','海南','台湾','云南','香港','澳门']

   var num = cityAll.indexOf(this.data.region[0])
   console.log(cityEasy[num])
   db.collection("city")
   .where({
     name:_.eq(cityEasy[num])
   })
   .update({
       data:{
       value:_.inc(1)
     }
   })
   .then(res=> {
         // res.data 包含该记录的数据
         this.getData();
         console.log(res)
       })

     this.setData({
       dialogShow: true,
       //lightshow:false
   })
   
 },

完整代码:

  1. js文件
import * as echarts from '../../ec-canvas/echarts';
import geoJson from './mapData.js';
//import mychart from './china.json';

const app = getApp();

var geoCoordMap = {
  '台湾': [121.5135,25.0308],
  '黑龙江': [127.9688, 45.368],
  '内蒙古': [110.3467, 41.4899],
  "吉林": [125.8154, 44.2584],
  '北京': [116.4551, 40.2539],
  "辽宁": [123.1238, 42.1216],
  "河北": [114.4995, 38.1006],
  "天津": [117.4219, 39.4189],
  "山西": [112.3352, 37.9413],
  "陕西": [109.1162, 34.2004],
  "甘肃": [103.5901, 36.3043],
  "宁夏": [106.3586, 38.1775],
  "青海": [101.4038, 36.8207],
  "新疆": [87.9236, 43.5883],
  "西藏": [91.11, 29.97],
  "四川": [103.9526, 30.7617],
  "重庆": [108.384366, 30.439702],
  "山东": [117.1582, 36.8701],
  "河南": [113.4668, 34.6234],
  "江苏": [118.8062, 31.9208],
  "安徽": [117.29, 32.0581],
  "湖北": [114.3896, 30.6628],
  "浙江": [119.5313, 29.8773],
  "福建": [119.4543, 25.9222],
  "江西": [116.0046, 28.6633],
  "湖南": [113.0823, 28.2568],
  "贵州": [106.6992, 26.7682],
  "云南": [102.9199, 25.4663],
  "广东": [113.12244, 23.009505],
  "广西": [108.479, 23.1152],
  "海南": [110.3893, 19.8516],
  '上海': [121.4648, 31.2891],
  '香港':[114.204522,22.263085],
  '澳门':[113.58206,22.14282],
};
var max = 607,
    min = 0; // todo 
var maxSize4Pin = 50,
    minSize4Pin = 0;

var convertData = function(data) {
    var res = [];
    for (var i = 0; i < data.length; i++) {
        var geoCoord = geoCoordMap[data[i].name];
        if (geoCoord) {
            res.push({
                name: data[i].name,
                value: geoCoord.concat(data[i].value),
            });
        }
    }
    return res;
};
const getPixelRatio = () => {
  let pixelRatio = 0
  wx.getSystemInfo({
    success: function (res) {
      pixelRatio = res.pixelRatio
    },
    fail: function () {
      pixelRatio = 0
    }
  })
  return pixelRatio
}
// console.log(pixelRatio)
var dpr = getPixelRatio()

var option = {
  backgroundColor: 'transparent',
  title: {
    subtext: '工大应援,点亮中国',
    left: 'center',
},
  tooltip: {
    trigger: 'item',
    backgroundColor: "#FFF",
    padding: [
      10,  // 上
      15, // 右
      8,  // 下
      15, // 左
    ],
    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: function (params) {
      if(typeof(params.value)[2] == "undefined"){
        return params.name + ' : ' + params.value;
      }else{
        return params.name + ' : ' + params.value[2];
      }
    }
  },
  geo: [
    {
      // 地理坐标系组件
      map: "china",
      roam: false, // 可以缩放和平移
      aspectScale: 0.8, // 比例
      layoutCenter: ["50%", "38%"], // position位置
      layoutSize: 370, // 地图大小,保证了不超过 370x370 的区域
      label: {
        // 图形上的文本标签
        normal: {
          show: true,
          textStyle: {
            color: "#E8E8E8",
            fontSize: '8'
          }
        },
        emphasis: { // 高亮时样式
          color: "#333",
          show: false
        }
      },
      itemStyle: {
        // 图形上的地图区域
        normal: {
          borderColor: "#FFD700",
          areaColor: "#87CEFF"
          //#000000 #87CEFF
        }
      }
    }
  ],
  visualMap: {
    show: true,
    min: 0,
    max: 607,
    left: 'left',
    top: 'bottom',
    text: ['high'], // 文本,默认为数值文本
    calculable: true,
    seriesIndex: [1],
    inRange: { 
        color: ['#63B8FF', '#FFD700','#EE0000'] //渐变颜色

    }
},
  series: [
    {
      name: '散点',
      type: 'scatter',
      coordinateSystem: 'geo',
     // data: convertData(data),
      symbolSize: function(val) {
          return val[2] / 100;
      },
      label: {
          normal: {
              formatter: '{b}',
              position: 'left',
              show: false,
              textStyle: {
                color: "rgba(0, 0, 0, 0.9)",
                fontSize: '8'
              }
          },
          emphasis: {
              show: true,
              textStyle: {
                color: "rgba(0, 0, 0, 0.9)",
                fontSize: '8'
              }
          }
      },
      itemStyle: {
          normal: {
              color: '#FFD700'
          }
      }
  },
  
    {
      type: 'map',
      mapType: 'china',
      geoIndex: 0,
      roam: false, // 鼠标是否可以缩放
      label: {
        normal: {
          show: false,
        },
        emphasis: {
          show: false
        }
      },
      itemStyle: {
        normal: {
            color: '#05C3F9',
            fontSize: '8'
        },
      },
     // data:citydata
  },
 
  
  {
    name: '气泡点',
    type: 'scatter',
    coordinateSystem: 'geo',
    symbol: 'pin', //气泡
    symbolSize: function(val) {
        var a = (maxSize4Pin - minSize4Pin) / (max - min);
        var b = minSize4Pin - a * min;
        b = maxSize4Pin - a * max;
        return (a * val[2] + b)/3;
    },
    label: {
        normal: {
            show: false,
            textStyle: {
                color: '#fff',
                fontSize: 8,
            }
        },
        formatter: '{@[6]}',
    },
   
    itemStyle: {
        normal: {
            color: '#F62157', //标志颜色
            fontSize: 8,
        }
    },
    //zlevel: 6,
   // data: convertData(citydata.sort(function(a, b) {return b.value - a.value;})),
},

{
    name: 'Top 5',
    type: 'effectScatter',
    coordinateSystem: 'geo',
    //data: convertData(citydata.sort(function(a, b) {return b.value - a.value; }).slice(0, 5)),
    symbolSize: function(val) {
        return val[2]/80;
    },
    showEffectOn: 'render',
    rippleEffect: {
        brushType: 'stroke'
    },
    hoverAnimation: true,
    label: {
        normal: {
            formatter: '{b}',
            position: 'right',
            show: false
        }
    },
   
    endcode:{
      label:2
    },
    itemStyle: {
        normal: {
            color: 'yellow',
            shadowBlur: 10,
            shadowColor: 'yellow'
        }
    },
   // zlevel: 1
}],

};

const db = wx.cloud.database()
const _ = db.command
var myMap = null;
Page({
  onShareAppMessage: function (res) {
    wx.showShareMenu({
      withShareTicket: true
    }) 
    return {
      title: '我为哈工大百年校庆应援!祝福工大生日快乐!',
      path: '/pages/light/light',
      imageUrl: 'https://6869-hit100-g6bma-1302265912.tcb.qcloud.la/2020.png?sign=b90eef1d7eabe42c1e5a362110b6a77c&t=1590806475',    
      success: function () { },
      fail: function () { }
    }
  },

  data: {
    ecMap: {
     // onInit: initChartMap
     lazyLoad: true //初始化加载
    },
    StatusBar: app.globalData.StatusBar,
    CustomBar: app.globalData.CustomBar,
    index: null,
    region: ['广东省', '深圳市', '南山区'],
    multiIndex: [0, 0, 0],
    customItem: '全部',
    dialogShow: false,
    //lightshow:true,
    buttons: [{text: '规格严格,功夫到家!  :)'}],
  },

  tapDialogButton(e) {
      this.setData({
          dialogShow: false,
      })
      if(e.detail){
        console.log(e.detail)
        wx.showShareMenu({
          withShareTicket: true
        }) 
        return {
          title: '我为哈工大百年校庆应援!祝福工大生日快乐!',
          path: '/pages/light/light',
          imageUrl: '/images/100.png',    
          success: function () { },
          fail: function () { }
        }
      }
     //console.log(e.detail)
  },

  lightHIT:function (){
    var cityAll = ['广东省','湖南省','黑龙江省','山东省','吉林省','辽宁省','内蒙古自治区','天津市','陕西省','山西省','宁夏回族自治区','新疆维吾尔自治区','西藏自治区','青海省','河北省','河南省','安徽省','浙江省','江苏省','上海市','重庆市','江西省','贵州省','海南省','台湾省','云南省','香港特别行政区','澳门特别行政区']
    var cityEasy = ['广东','湖南','黑龙江','山东','吉林','辽宁','内蒙古','天津','陕西','山西','宁夏','新疆','西藏','青海','河北','河南','安徽','浙江','江苏','上海','重庆','江西','贵州','海南','台湾','云南','香港','澳门']

    var num = cityAll.indexOf(this.data.region[0])
    console.log(cityEasy[num])
    db.collection("city")
    .where({
      name:_.eq(cityEasy[num])
    })
    .update({
        data:{
        value:_.inc(1)
      }
    })
    .then(res=> {
          // res.data 包含该记录的数据
          this.getData();
          console.log(res)
        })

      this.setData({
        dialogShow: true,
        //lightshow:false
    })
    
  },

  bindPickerChange: function (e) {
    console.log('picker发送选择改变,携带值为', e.detail.value)
    this.setData({
      index: e.detail.value
    })
  },
 
  MultiColumnChange(e) {
    let data = {
      multiArray: this.data.multiArray,
      multiIndex: this.data.multiIndex
    };
    data.multiIndex[e.detail.column] = e.detail.value;
    switch (e.detail.column) {
      case 0:
        data.multiIndex[1] = 0;
        data.multiIndex[2] = 0;
        break;
      case 1:
        switch (data.multiIndex[0]) {
          case 0:
            break;
          case 1:
            break;
        }
        data.multiIndex[2] = 0;
        break;
    }
    this.setData(data);
  },
 
  bindRegionChange: function (e) {
    console.log('picker发送选择改变,携带值为', e.detail.value)
    this.setData({
      region: e.detail.value
    })
  },
   /**
 1. 生命周期函数--监听页面加载
   */
  onLoad: function (options) {
    this.echartsComponnet = this.selectComponent('#mychart-dom-map');
    this.getData(); //获取数据
  },

  onReady() {
  },
  
  getData:function()
  {
    wx.cloud.callFunction({
      name:"getCity"
    })
    .then(res=>{
      //console.log(res.result.data)
      const citydata=[];
      for(var i=0;i<res.result.data.length;i++){
        citydata.push(res.result.data[i])
     }
     //console.log(citydata)
     for(var i=0;i<citydata.length;i++){
        delete citydata[i]._id;
        delete citydata[i]._openid;
     }
     // console.log(citydata)
  
     // option.yAxis[0].data = note;
      option.series[0].data =  convertData(citydata);
      option.series[1].data = citydata;
      option.series[2].data = convertData(citydata.sort(function(a, b) {return b.value - a.value;}));
      option.series[3].data = convertData(citydata.sort(function(a, b) {return b.value - a.value;}).slice(0, 5));
      if(!myMap){
        this.init_ChartMap();
      }else{
        myMap.clear();
        this.init_ChartMap();
      }
    })
  },


  init_ChartMap: function() {
    this.echartsComponnet.init((canvas, width, height)=>{
    myMap = echarts.init(canvas, null, {
          width: width,
          height: height,
          devicePixelRatio: dpr
        });   
      myMap.showLoading(); // 首次显示加载动画
      canvas.setChart(myMap);
      echarts.registerMap('china', geoJson);  // 绘制中国地图

      myMap.setOption(option);
      myMap.hideLoading(); // 隐藏加载动画
      return myMap;
    });
  }
  
});
  1. json文件
{
  "usingComponents": {
   "ec-canvas": "../../ec-canvas/ec-canvas",
   "mp-dialog": "/miniprogram_npm/weui-miniprogram/dialog/dialog"
 }
}
  1. wxml文件
<!--index.wxml-->

<view class="container">
<text class="word1">哈尔滨工业大学百年校庆</text>
 <ec-canvas id="mychart-dom-map" canvas-id="mychart" ec="{{ ecMap }}"></ec-canvas>
  <text class="word2"> 我为哈工大百年校庆应援!</text>
 	<view class="cu-form-group">
     <view class="title">地址选择</view>
     <picker mode="region" bindchange="bindRegionChange" value="{{region}}" custom-item="{{customItem}}">
       <view class="picker">
         {{region[0]}}{{region[1]}}{{region[2]}}
       </view>
     </picker>
 	</view> 

  <view style="width:500rpx;display: flex;flex-direction: row; justify-content:space-between; padding:10rpx;">
     <button type="primary" bindtap="lightHIT" >应援按钮</button>
     <button type="primary" plain="true" open-type="share">分享给朋友</button>
   </view>

   <mp-dialog title="为哈工大百年校庆应援成功!" show="{{dialogShow}}" bindbuttontap="tapDialogButton" buttons="{{buttons}}">
       <image style="width: 160px; height: 125px;"  src="https://6869-hit100-g6bma-1302265912.tcb.qcloud.la/2020.png?sign=b90eef1d7eabe42c1e5a362110b6a77c&t=1590806475"></image>
   </mp-dialog>
    
</view>

  1. wxss文件
/**index.wxss**/
ec-canvas {
 width: 100%;
 height: 100%;
 padding:300rpx,0rpx,10rpx,10rpx;
}

#mychart-dom-map{
 width:100%;
 height:800rpx;
 padding:100rpx,0rpx,20rpx,20rpx;
}

.button-sp-area{
 margin: 0 auto;
 width: 50%;
 padding-top:10rpx;
}

.word2{
 font-size:18px;      /*设置文字字号*/
 color:red;           /*设置文字颜色*/
 font-weight:bold;    /*设置字体加粗*/
 font-family:"微软雅黑";  
}

.word1{
 font-size:19px;      /*设置文字字号*/
 color:black;           /*设置文字颜色*/
 font-weight:bold;    /*设置字体加粗*/
 font-family:"微软雅黑";  
}

.container {
 position: absolute;
 top: 10rpx;
 bottom: 0;
 left: 0;
 right: 0;

 height: 100%;
 display: flex;
 flex-direction: column;
 align-items: center;
 justify-content: space-between;

 box-sizing: border-box;
} 

效果图

  • 总体布局
    在这里插入图片描述

  • 进入工大应援
    在这里插入图片描述

  • 选择地区后点亮

在这里插入图片描述

  • 7
    点赞
  • 41
    收藏
    觉得还不错? 一键收藏
  • 10
    评论
评论 10
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值