序 完成效果 代码地址
其实前端使用地图真的没有那么难,任何事物都是讲究方法的,前端使用地图也是一样的。
地图的一些基本知识
geoJson
维基百科这样介绍:GeoJSON是一种基于JSON的地理空间数据交换格式,它定义了几种类型JSON对象以及它们组合在一起的方法,以表示有关地理要素、属性和它们的空间范围的数据。
// 表示一个点
{
"type": "Point",
"coordinates": [30, 10]
}
// 表示一个线
{
"type": "LineString",
"coordinates": [
[30, 10], [10, 30], [40, 40]
]
}
// 表示一个面(多边形)
{
"type": "Polygon",
"coordinates": [
[[30, 10], [40, 40], [20, 40], [10, 20], [30, 10]]
]
}
// 特殊的面 (特殊多边形)
{
"type": "Polygon",
"coordinates": [
[[35, 10], [45, 45], [15, 40], [10, 20], [35, 10]],
[[20, 30], [35, 35], [30, 20], [20, 30]]
]
}
地图的坐标系
- 地球上同一个地理位置的经纬度,在不同的坐标系中,会有少许偏移,国内目前常见的坐标系主要分为三种:
- 地球坐标系——WGS84:常见于 GPS 设备,Google 地图等国际标准的坐标体系。
- 火星坐标系——GCJ-02:中国国内使用的被强制加密后的坐标体系,高德坐标就属于该种坐标体系。
- 百度坐标系——BD-09:百度地图所使用的坐标体系,是在火星坐标系的基础上又进行了一次加密处理。
- 其84坐标系内网使用较多,具有精度高,偏差小的特点。
- 高德开放平台提供坐标转换api
在vue中加载地图
- 高德、百度、腾讯地图文章很多了,咱看另一个地图minedata,四维图新旗下的地图,与bat的地图相比缺少一些知名度,但是因为他是商用地图。文档会比较完善。
- 初始化一个vuecli项目(默认vue2.x, 其实3.x 套路也是一样的),清理下无用的代码。
- 按照官网提示在项目的
index.html中引入地图所需文件
<!-- 引入MineMap API插件 抄官网的-->
<link rel="stylesheet" href="https://minedata.cn/api/static/demo/js-api/zh/css/demo.css">
<link rel="stylesheet" href="https://minedata.cn/minemapapi/v2.1.0/minemap.css">
<script src="https://minedata.cn/minemapapi/v2.1.0/minemap.js"></script>
- 创建一个
map.vue文件,在app.vue的文件中当组件引入 map文件如下官网例子
<template>
<div class="box">
<div id="map"></div>
</div>
</template>
<script>
export default {
name: "map",
data() {
return {
mapObj: null
}
},
mounted() {
// dom 初始化完成才能加载地图
this.initMap()
},
methods: {
initMap() {
let minemap = window.minemap
minemap.domainUrl = 'https://minedata.cn';
minemap.dataDomainUrl = ['https://datahive.minedata.cn', 'https://datahive01.minedata.cn', 'https://datahive02.minedata.cn', 'https://datahive03.minedata.cn', 'https://datahive04.minedata.cn'];
minemap.spriteUrl = 'https://minedata.cn/minemapapi/v2.1.0/sprite/sprite';
minemap.serviceUrl = 'https://mineservice.minedata.cn/service/';
minemap.appKey = '16be596e00c44c86bb1569cb53424dc9';
minemap.solution = 12877;
this.mapObj = new minemap.Map({
container: 'map', // 地图容器 对应 template 中,id 等于 map 的 div
style: 'https://mineservice.minedata.cn/service/solu/style/id/12877', // 地图主题
center: [116.46, 39.92], // 地图初始化中心点
zoom: 10, // 地图初始化默认比例
maxZoom: 17, // 最大比例
minZoom: 3 // 最小比例
});
}
}
}
</script>
vh
<style scoped>
.box {
width: 100vw;
height: 100vh;
}
#map {
width: 100%;
height: 100%;
}
</style>
在地图上加载一个点
// 扩展上述方法 并在 initMap函数中调用
addMarker () {
let el = document.createElement('div');
el.id = 'marker';
el.style["background-image"] = "url(https://minedata.cn/api/static/demo/js-api/zh/images/park.png)";
el.style["background-size"] = "cover";
el.style.width = "50px";
el.style.height = "50px";
el.style["border-radius"] = "50%";
// 添加一个信息窗体
let popup = new minemap.Popup({offset: [0, -48]}).setText("我是一个固定信息窗体")
new minemap.Marker(el, {offset: [-25, -50]})
.setLngLat([116.46,39.92])
.setPopup(popup) // 信息窗体绑定到marker
.addTo(this.mapObj)
}
在地图上加载多个点
- 多个点与一个点其实没有本质的区别,不过在做大数据量(点位过万)点位展示时,本地图不建议使用 marker,会导致地图缩放等操作卡顿,咨询官方回复建议使用 geojson的方式自定义点位展示,他们做了优化。
- 在其 MineMap for 2D API V2.0.0 上线 2019-12-02,存在
addMarkers方法,但是在2.1.0貌似是删除了这个方法。
// addMarkers 方法 需要在地图加载完成后使用
let vm = this
this.mapObj.on("load",function(){
vm.addMarker()
vm.addMarkers()
})
// 创建 addMarkers 方法,添加到 initMap 方法中使用
addMarkers() {
let pointList = [
[116.28841,39.895239],
[116.351067,39.894712],
[116.321026,39.916308]
]
pointList.map((item,index) => {
let el = document.createElement('div');
el.id = 'marker';
el.style["background-image"] = "url(https://minedata.cn/api/static/demo/js-api/zh/images/park.png)";
el.style["background-size"] = "cover";
el.style.width = "50px";
el.style.height = "50px";
el.style["border-radius"] = "50%";
let popup = new minemap.Popup({offset: [0, -48]}).setText(`我是多个添加的marker${index} 信息窗体`)
new minemap.Marker(el, {offset: [-25, -50]})
.setLngLat(item)
.setPopup(popup)
.addTo(this.mapObj)
})
}
在地图上加载一个线
- 两点连成线
// addLine 方法 需要在地图加载完成后使用
let vm = this
this.mapObj.on("load",function(){
vm.addMarker()
vm.addMarkers()
vm.addLine(vm.mapObj) // 传入地图实例
})
// 创建添加线的方法 addLine
addLine(map) {
// 将线的geo数据 添加到地图的数据源
map.addSource("arrowSource", {
"type": "geojson",
"data": {
"type": "Feature",
"properties": {},
"geometry": {
"type": "LineString",
"coordinates": [
[116.221462,39.873505],
[116.585227,39.8822],
[116.282574,39.728947]
]
}
}
});
// 将线的数据源添加到地图
map.addLayer({
"id": "line",
"type": "line",
"source": "arrowSource",
"paint": {
"line-color": "#15bbf2",
"line-width": 4
}
})
}
// 同样将方法添加到
在地图上加载一个面
- 三点连成面
// addPolygon 方法 需要在地图加载完成后使用
let vm = this
this.mapObj.on("load",function(){
vm.addMarker()
vm.addMarkers()
vm.addLine(vm.mapObj) // 传入地图实例
vm.addPolygon(vm.mapObj) // 传入地图实例
})
// 创建addPolygon方法
addPolygon(map) {
// 将面的geo数据 添加到地图的数据源
map.addSource("fillSource", {
"type": "geojson",
"data": {
"type": "Feature",
"properties": {},
"geometry": {
"type": "Polygon",
"coordinates": [
[
[116.25116,39.921311],
[116.370465,39.931974],
[116.28429,39.884702],
[116.25116,39.921311],
]
]
}
}
});
map.addLayer({
"id": "fillLayer",
"type": "fill",
"source": "fillSource",
"layout": {
"visibility": "visible",
},
"paint": {
"fill-color": "#00ff00",
"fill-opacity": 0.8,
"fill-outline-color": "#ff0000"
},
"minzoom": 7,
"maxzoom": 17.5
});
}
切换地图主题颜色
- 这个就比较简单了,一般官方都会提供相应的api的
// template
<div class="butBox">
<button @click="setMapTheme(12877)">默认</button>
<button @click="setMapTheme(12878)">深色</button>
</div>
// methods 中的 setMapTheme方法
setMapTheme(id) {
if (this.mapObj) {
this.mapObj.appKey = '16be596e00c44c86bb1569cb53424dc9';
this.mapObj.solution = id;
this.mapObj.setStyle('https://mineservice.minedata.cn/service/solu/style/id/' + id);
}
}
后话
- 有时候我们会有一个这样的需求,在地图上画出 各个省市区的范围,那么地图区划数据从哪里来呢?
- 其实你明白了一种地图的使用,也大概就懂了其他地图的使用。而且主流地图的使用方式都是大同小异。
- 要使用 你带先加载 sdk
- 然后你要初始化地图
- 然后在地图上做一些动作,做加载点 面 线
- 有的地图会有图层的概念,有的则没有
- 这一切的前提就是你需要认真阅读文档,一款给大众使用的地图 ,就决定了文档不会太难,不要说
leafletjs那是真的需要认真看的。