vue大屏中使用echarts实现区域地图

12,450 阅读3分钟

081916570879_0微信截图_222220210819165459.png

一:实现思路

我接触的地图开发分为两种:1需要详细地图数据 2大体总览 ,这次开发就是大体总览,我触到的图例组件库有:chartsl7 ,综合考虑决定用charts

echarts中有两种实现地图的方式:geo(地理坐标系) servers.map

1:geo支持缩放功能并搭配其它系列组件标线\标点

2:servers.map在echarts3版本后就不建议使用 markLine 和 markPoint标点和线

综合考虑使用geo

geo存在两种渲染格式:svgjson,只需要轮廓选用json文件 ,json文件有高德的公开资源可以下载:地图下载

二:地图引入-基础实现地图

引入echarts(别忘了安装)

//main.app中
import echarts from 'echarts'
Vue.prototype.$echarts = echarts

页面引入echatrs图表

<template>
  <div>


     //echarts需要一个有具体宽高的容器做渲染容器
    <div id="centerMap" ref="centerMap"  style=" height:990px;width:660px;padding: 25px " />
  </div>
</template>

<script>

export default {
  name: 'echart',
  data () {
    return {
      chart:undefined,
     storeData:store,
    options:{
      
    }

    };
  },
  components: {

  },
  methods: {
    initChart () {
      // 初始化echart
      this.chart = this.$echarts.init(this.$refs.centerMap)
    
      

      )   },

  },
  mounted() {
    this.initChart()
   
  }


};

引入josn地图文件,增加echarts组件

//引入下载的json文件
import zibo from '@/assets/zibo.json'
//data增加echarts需要的otions设置
options:{
  animation:false,
  //geo方式地理坐标系组件。
  geo: {
    map: 'zibo',
    zoom: 1.2,
    label: {
      show:true,
      color:'#fff',
      fontSize: 25,
      // 高亮状态下的多边形和标签样式。

    },
    // 选中状态下的多边形和标签样式
    emphasis: {
      itemStyle:{
        color: 'rgba(51, 69, 89, .5)', //地图背景色
        borderColor: '#516a89', //省市边界线00fcff 516a89
        borderWidth: 1,
      },
      label:{
        color:'#fff'
      }

    },
    // aspectScale:0.75, //长宽比
    roam: true, //是否允许缩放
    itemStyle: {
      normal: {
        color: 'rgba(51, 69, 89, .5)', //地图背景色
        borderColor: '#516a89', //省市边界线00fcff 516a89
        borderWidth: 1,
      },
 
    },


  }
}

//初始化方法中增加调用json实现地图的操作
initChart () {
  // 初始化echart
  //记录不同地图下,合适的原点大小
  //

  this.chart = this.$echarts.init(this.$refs.centerMap)

  this.$echarts.registerMap('zibo',zibo)
  this.chart.setOption(this.options, true)

  )

三:增加地理坐标系上的散点图

地名转经纬度

散点图要在地图上展示,需要明确的经纬度.如果你和我一样只有地点名,没有经纬度的话,可以通过百度或高德的地图服务转换为经纬度,需要申请自己的开发者key

//这是我写的转换页面,很简陋.调用的地址是JSONServer服务
<!DOCTYPE html>
<html>

<head>
    <meta name="viewport" content="initial-scale=1.0, user-scalable=no" />
    <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
    <title>Hello, World</title>
    <style type="text/css">
        html {
            height: 100%
        }

        body {
            height: 100%;
            margin: 0px;
            padding: 0px
        }

        #container {
            height: 100%
        }
    </style>
    <script type="text/javascript"
        src="https://api.map.baidu.com/api?v=1.0&type=webgl&ak=这里填你需要的开发者key">
        </script>
    <style>
        body,
        html {
            width: 100%;
            height: 100%;
            padding: 0;
            margin: 0;
        }

        #container {
            width: 100%;
            height: 100%;
            overflow: hidden;
        }

        #result {
            position: fixed;
            top: 10px;
            right: 10px;
            width: 350px;
            height: 480px;
            line-height: 30px;
            text-align: center;
            background: #fff;
            box-shadow: 0 2px 6px 0 rgba(27, 142, 236, 0.5);
            border-radius: 7px;
            z-index: 99;
        }

        #result>div:first-child {
            width: 100%;
            height: 40px;
            text-align: center;
            line-height: 40px;
            background: #00BFFF;
            border-radius: 7px 7px 0px 0px;
            color: #fff;
        }

        #result ul {
            list-style-type: none;
            margin: 0;
            padding: 0;
        }

        #result ul li {
            color: #000;
            padding: 7px;
            font-size: 14px;
            text-align: justify;
            border-bottom: 1px solid #D3D3D3
        }

        #result>div:last-child {
            display: flex;
            align-items: center;
            justify-content: flex-end;
            padding: 10px;
        }

        .btn {
            width: 100px;
            height: 35px;
            color: #fff;
            font-size: 14px;
            ;
            border-radius: 5px;
            background: #00BFFF;
            box-shadow: none;
        }

        .btn:hover {
            cursor: pointer;
        }
    </style>
</head>

<body>
    <div id='container'></div>
    <div id='result'>
        <div>批量地址解析</div>
        <div>
            <button onclick='bdGEO()' class='btn'>批量解析</button>
        </div>
    </div>

    <script>
        var map = new BMapGL.Map('container');
        map.centerAndZoom(new BMapGL.Point(118.031258, 36.813892), 12);
        map.enableScrollWheelZoom(true);
        var myGeo = new BMapGL.Geocoder();
        var adds;
        fetch('http://localhost:8090/store', {
            method: 'GET'
        }).then(res => {
            if (res.ok) {
                return res.json(); // 返回一个promise对象
            } else {
                return Promise.reject('something went wrong!')
            }
        }).then(data => {

            adds = data
            // 继续处理响应数据
        }).catch(err => {
            console.log("网络出错" + err);
        });


        var index = 0;
        function bdGEO() {

            if (index < adds.length) {
                var add = adds[index];
                geocodeSearch(add);
                index++;
            }
        }
        function geocodeSearch(add) {
                      if(index < adds.length){
                          setTimeout(window.bdGEO,400);
                      } 

            myGeo.getPoint(add.ab9, function (point) {
                console.log(index)
                
                if (point) {
                    console.log(point.c4)
                    add.coords = [[point.lng, point.lat] ,[ 118.031258 ,36.813892 ]];
                    fetch('http://localhost:8090/storeDispose', {
                    method: 'POST', // or 'PUT'
                    body: JSON.stringify(add), // data can be `string` or {object}!
                    headers: new Headers({
                        'Content-Type': 'application/json'
                    })
                }).then(res => res.json())
                    .catch(error => console.error('Error:', error))
                    .then(response => console.log('Success:', response))


                    //var address = new BMapGL.Point(point.lng, point.lat);
                    //   addMarker(address,new BMapGL.Label(index+":"+add,{offset:new BMapGL.Size(10,-10)}));
                } else {
                    alert('您选择的地址没有解析到结果!');
                }
               



            }, "淄博市");
        }
        // 编写自定义函数,创建标注
        function addMarker(point, label) {
            var marker = new BMapGL.Marker(point);
            map.addOverlay(marker);
            marker.setLabel(label);
        }
    </script>
</body>

</html>
//转换完成的数据格式
[{  "ab4": "xxxxxxx",  "ab9": "xxxxxxxxxxxx",  "coords": [    [      117.843449058821,      36.52321269463374    ],
    [      118.031258,      36.813892    ]
  ],
  "id": 1
},
{
  "ab4": "xxxxxxxxxxxx",
  "ab9": "xxxxxxxxxxxxxxxx",
  "coords": [
    [
      118.2040667091881,
      36.89458786758729
    ],
    [
      118.031258,
      36.813892
    ]
  ],
  "id": 2
},


]

增加散点图

// 引入上面转换的json格式数据
// option中散点图设置
series:[
  //  所在地圆环
  {
    type: 'effectScatter',
    coordinateSystem: 'geo',
    zlevel: 2,
    rippleEffect: { //涟漪特效
      period: 20, //动画时间,值越小速度越快
      brushType: 'stroke', //波纹绘制方式 stroke, fill
      scale: 4 //波纹圆环最大限制,值越大波纹越大
    },
    label: {
      normal: {
        show: false,
        position: 'right', //显示位置
        offset: [5, 0], //偏移设置
        formatter: function(params) { //圆环显示文字
          return params.data.name;
        },
        fontSize: 18
      },
      emphasis: {
        show: true,
        color:'#fff',
      }
    },
    symbol: 'circle',
    symbolSize: 2,
    itemStyle: {
      normal: {
        show: false,
        color: '#1e90ff'
      }
    },
    data:store.map(item => {
      return {
        name:item.ab4,
        value:item.coords[0].concat([0])
      }

    })
  },


]


四:基础效果完成后的一些问题

地理坐标系上的散点图未随地图一起放大缩小

经查询echarts-散点没有相关放大缩小的配置,在搜索引擎的帮助下发现echarts存在监听geo缩放的事件georoam,这个事件在文档里搜索了,没有搜索到.互联网大神是真的牛皮

监听georoam事件,在执行方法中根据param参数与echarts属性调整echart中属性,动态调整散点图的大小 georoam事件的参数

//如果是缩放的话
{
  componentType: "geo"
  geoId: "\u0000series\u00000\u00000"
 originX: 270
  originY: 425
  type"georoam"
  zoom: 1.1
}

//如果是拖拽的话
{
  componentType: "geo"
  dx: 0
  dy: 0
  geoId: "\u0000series\u00000\u00000"
  type"georoam"
}
//增加监听事件
this.chart.on('georoam', (params)=> {
//如果是拖拽就拒绝
 if(parames.dy || parames.dx) return

var _option =   this.chart.getOption()
//地图大小
var _zoom =  _option.geo[0].zoom
//药店的圆环属性--大小
var _symbolSize =  _option.series[1].symbolSize
console.log(_zoom)

_option.series[1].symbolSize = 2 * _zoom
_option.series[0].symbolSize = 4 * _zoom

//如果不清除的话,散点图改变后会导致与geo地理坐标系偏移
this.chart.clear()
this.chart.setOption(_option)

}

)

监听事件导致的卡顿问题

监听georoam事件后,发现事件会频繁的触发,一次缩放会触发几百次事件.

暂时考虑到的方案有:

  1. option中禁止动画
  2. 散点图调整增加防抖处理
//option中增加动画,不太确定有多少效果
options:{

animation:false,
}
//引入防抖函数
import  { debounce} from '@/utils/index'

//修改监听事件调用的方法

this.chart.on('georoam', debounce(this.oveFow,500)


//增加-调整散点图大小的方法

oveFow(parames){
  console.log(parames)
  // if(parames.dy || parames.dx) return

  var _option =   this.chart.getOption()
  var _zoom =  _option.geo[0].zoom
  //药店的圆环属性
  var _symbolSize =  _option.series[1].symbolSize
  console.log(_zoom)

  _option.series[1].symbolSize = 2 * _zoom
  _option.series[0].symbolSize = 4 * _zoom

  this.chart.clear()
  this.chart.setOption(_option)
}

不会制作gif动图,没法展示效果了

五:参考文章

1. 实现echarts地图监听缩放事件效果_qq_42980124的博客-CSDN博客

2.Documentation - Apache ECharts