vue3项目中使用mapv
mapv是百度地图官方提供的地图数据可视化开源项目,提供了很多效果酷炫的绘图api
mapv地址在这里,示例图在这里
先解释为什么要用mapv
- echarts画的地图,都是行政区划,就算是geo地图,也只能在行政区划地图上添加一些地理信息点,而不能直接使用百度地图(只是个例子,也可以是高德)作为底图来展示地理信息数据
- 要想在使用百度地图,就得使用BMapGL
- BMapGL只能绘制一些比较简单的点线面图,如果想要画出复杂炫酷的地图可视化数据,就得使用mapv GL
- Mapv GL一般会配合MapV使用(是一般情况下,有时候也会单独用)
说来说去,就是地图可视化离不开BMapGL,而BMapG又离不开Mapv GL
目前,百度地图官方只提供了React-BMapGL文档
换句话说,如果用前端开发框架的话,得用react。当然也可以用vue,但是非常麻烦,折腾了很久,找到了一套可行的方案
先上效果,其实实现的就是mapv官网上的一个散点图例子
总体来说,要经过这么几个步骤:
- 网页入口文件中引入bmapgl
- npm安装mapv和mapv gl
- 组件中引入并使用bmapgl以及mapv画图
一、网页入口文件中引入bmapgl
在vue项目的根目录的index.html文件中在线引入bmapgl
如下
<!DOCTYPE html>
<html lang="en"><head><meta charset="UTF-8"><link rel="icon" href="/favicon.ico"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Vite App</title><!-- <script type="text/javascript"src="https://api.map.baidu.com/getscript?v=3.0&ak=ak&services=&t=20240108120956"></script><link rel="stylesheet" type="text/css" href="http://api.map.baidu.com/res/webgl/10/bmap.css"> --><!-- <script type="text/javascript" src="https://registry.npmmirror.com/echarts/5.4.3/files/dist/extension/bmap.min.js"></script> -->
</head><body><div id="app"></div><script type="module" src="/src/main.js"></script><script type="text/javascript" src="https://api.map.baidu.com/getscript?v=1.0&type=webgl&ak=自己的ak" async="async"></script></body></html>
这里有三个坑:
-
从我注释的代码中可以看出来,我尝试了在不同的地方引入百度地图,但是我最终选择在dom的最后面引入,虽然我不确认这样是不是脱坑的解决方案,但是我还是建议这么写,因为dom的渲染是从上到下的,听说要等dom渲染完成再引入会不容易报错🥶
-
我在引入的过程中,添加了
async="async"
,这是HTML5新增属性,需要Chrome、FireFox、IE9+浏览器支持,这么做的目的是让程序等待webgl加载完成在执行别的,其实这么做的目的和上面那个一样,都是因为控制台一直报错BMapGL未定义,查了一下,说异步导入可以解决,但是不写这个也可以,建议还是加上 -
官网给的引入脚本地址是
https://api.map.baidu.com/api?v=1.0&type=webgl&ak=自己的ak
,如果这么导入,控制台老是报警,不影响页面展示,报警内容如下:A parser-blocking, cross site (i.e. different eTLD+1) script, https://api.map.baidu.com/getscript?type=webgl&v=1.0&ak=xxx&services=&t=20240129120837, is invoked via document.write. The network request for this script MAY be blocked by the browser in this or a future page load due to poor network connectivity. If blocked in this page load, it will be confirmed in a subsequent console message. See https://www.chromestatus.com/feature/5718547946799104 for more details.
如果没有强迫症的话,就不用改地址,听说改地址后会导致某些样式不起作用,也没测试过
二、mapv及mapv gl安装
没啥好说的,vue中使用,第一选择当然是通过包管理工具安装
npm i mapvgl
npm i mapv
个人安装的两个版本如下
“mapv”: “^2.0.62”,
“mapvgl”: “^1.0.0-beta.188”,
其实还有其他方式,可以通过cdn或者脚本引入,我没尝试,效果也未知
三、组件中的写法
我直接上我的完整代码(不知道为啥,搜索了网上一堆的代码,没有一个给出完整的代码,都是片段)
<template><div class="container"><div id="map" class="map"></div></div>
</template><script setup>
import { ref, onMounted } from 'vue'
import * as mapv from 'mapv'
import * as mapvgl from 'mapvgl'
import { whiteStyle } from '@/utils/mapvCommon'
const init = () => {var map = new BMapGL.Map("map", {style: { styleJson: whiteStyle }});var point = new BMapGL.Point(105.403119, 38.028658);map.centerAndZoom(point, 5);map.enableScrollWheelZoom(true);const data = ref([])const cities = ['北京', '天津', '上海', '重庆', '石家庄', '太原', '呼和浩特', '哈尔滨','长春', '沈阳', '济南', '南京', '合肥', '杭州', '南昌', '福州', '郑州','武汉', '长沙', '广州', '南宁', '西安', '银川', '兰州', '西宁', '乌鲁木齐','成都', '贵阳', '昆明', '拉萨', '海口']let randomCount = 300while (randomCount--) {var cityCenter = mapv.utilCityCenter.getCenterByCityName(cities[parseInt(Math.random() * cities.length, 10)]);data.value.push({geometry: {type: 'Point',coordinates: [cityCenter.lng - 2 + Math.random() * 4, cityCenter.lat - 2 + Math.random() * 4]},properties: {count: parseInt(4 * Math.random(), 10)}});}var view = new mapvgl.View({map: map});var pointLayer = new mapvgl.PointLayer({blend: 'lighter',size: 10,color: function (item) {if (item.properties.count === 1) {return 'rgb(191, 67, 66, 0.8)';}else if (item.properties.count === 2) {return 'rgb(211, 139, 93, 0.8)';}else if (item.properties.count === 3) {return 'rgb(44, 85, 48, 0.8)';}else {return 'rgb(115, 158, 130, 0.8)';}}});view.addLayer(pointLayer);pointLayer.setData(data.value);
}
onMounted(() => {init()
})
</script><style lang="scss" scoped>
.map {height: 100%;width: 100%;
}
</style>
组件中引入了一个whiteStyle,它也是mapgl官方给的地图样式,它的地址在这里,我的写法是在utils文件夹下自己新建一个mapvCommon.js文件,然后对外按需暴露
画图的代码也是mapgl官方给的示例,地址在这里
这里依然有坑,官网给的原生js写法,我把画图写在了生命周期钩子中,因为老是报错,图也出不来。估计依然是dom渲染的问题
总结一下:
目前mapv在vue框架中的使用案例还是比较少的,官网给的示例都是原生写法,写在项目中不是这里报错就是那里报错🙈,几乎可以把人整崩溃。不知道怎么回事,百度地图的开发团队似乎更加倾向于react或者原生,而对vue的支持明显不够,对国内开发者不太友好。不管是mapv还是echarts,似乎都存在各种各样的坑,尤其是设计地图的开发展示
另外,开源是一把双刃剑,有些开源的作者简直提供的就是一堆垃圾代码,如果不能维护好,建议先不要开源(个人意见)
真的是春节前的最后一篇技术博客了,希望来源永无bug。。