Mapbox GL JS 地图上动态加载饼状图

最近要在地图上动态展示各行政区的统计数据,要求是饼图。因为同时存在多个饼图,所以Mapbox的echartsLayer插件没办法用。但是和Mapbox的官方一个实例有些类似,博主改造了一下。实现了下面的效果:

效果

原理

给Mapbox添加自定义的Marker,其中的内容使用svg填充,根据数据动态计算svg内的path。

代码

<template>
  <div id="map">

  </div>
</template>

<script>
import mapboxgl from 'mapbox-gl';

export default {
  name: 'HelloWorld',
  data() {
    return {
      map: null,
    }
  },
  mounted() {
    mapboxgl.accessToken =
      'pk.eyJ1IjoiaGFtYnVnZXJkZXZlbG9wIiwiYSI6ImNqNXJtZjF4ZzB3em4yd21pZmVqbHlleDAifQ.I9eqVjtotz7jaU7XcJm9pQ';
    let map = new mapboxgl.Map({
      container: "map",
      style: "mapbox://styles/mapbox/light-v10",
      zoom: 0.3,
      center: [0, 20]
    });
    this.map = map;
    //解决canvas渲染不正确
    map.on("styledata", function () {
      map.resize();
    });
    map.on("load", e => {
      for (let i = 0; i < 10; i++) {
        let el=this.createDonutChart();
        new mapboxgl.Marker({element: el}).setLngLat([this.getRandomLng(),this.getRandomLat()]).addTo(map);
      }
    })


  },
  methods: {

    getRandomLat(){
      return Math.random() * 90
    },
    getRandomLng(){
      return Math.random() * 180
    },

    // 生成随机数据
    getData(){
      return [Math.floor(Math.random() * 11),Math.floor(Math.random() * 11),Math.floor(Math.random() * 11)]
    },
    createDonutChart() {
      //随机数据
      let data=this.getData();
      let total=data[0]+data[1]+data[2];
      if(total===0){return }

      //半径和直径
      let w = 100;
      let r = w/2;
      let fontSize=14;
      //角度计算
      let degree1=data[0]/total*2*Math.PI;
      let degree2=data[1]/total*2*Math.PI;
      //计算大角小角
      let largeArcFlag1=degree1>Math.PI?1:0;
      let largeArcFlag2=degree2>Math.PI?1:0;
      //计算终点位置
      let endX1,endY1,endX2,endY2;
      endX2=r-r*Math.sin(degree2);
      endX1=r+r*Math.sin(degree1);
      endY2=r-r*Math.cos(degree2);
      endY1=r-r*Math.cos(degree1);
      //拼接SVG
      let html = '<svg width="' + w + '" height="' + w + '" viewbox="0 0 ' + w + ' ' + w +
        '" text-anchor="middle" style="font: ' + fontSize + 'px sans-serif"><circle cx="' + r + '" cy="' + r + '" r="' + r +
        '" fill="#FF0000" />';
      let greenArea = `<path d="
		M${r} ${r}
		L${r} 0
		A${r} ${r} 0 ${largeArcFlag1} 1 ${endX1} ${endY1}
	" fill="#00FF00"/>`

      let blueArea = `<path d="
		M${r} ${r}
		L${r} 0
		A${r} ${r} 0 ${largeArcFlag2} 0 ${endX2} ${endY2}
	" fill="#0000FF"/>`
      html += blueArea;
      html += greenArea;
      html+="</svg>"

      let el = document.createElement('div');
      el.innerHTML = html;
      return el.firstChild;
    },


  }
}
</script>

<style>
body, html {
  padding: 0;
  margin: 0;
}

#map {
  width: 100%;
  height: 100%;
}
</style>

 

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 点我我会动 设计师:白松林 返回首页