由于B/S端地图采集的经纬度数据使用wgs84坐标系,uniapp提供的原生map组件坐标系为gci02,所以改使用leaflet.js来开发地图功能
vue2 下
可以采取静态包引入的模式,将leaflet.js下载到本地,放在/static中
APP.vue页面,style中引入leaflet样式
<style>
/*每个页面公共css */
@import url('static/css/leaflet.css');
//leaflet.markercluster.js为点聚合插件根据需要下载引入,
@import url('static/css/MarkerCluster.css');//点聚合
@import url('static/css/MarkerCluster.Default.css');//点聚合
</style>
index.vue页面,引入leaflet组件
<template>
<view class="content">
<leaflet></leaflet>
</view>
</template>
<script>
import leaflet from '../../components/leaflet/leaflet.vue';
export default {
components: {
leaflet
},
data() {
return {
title: 'Hello'
};
},
onLoad() {},
methods: {}
};
</script>
<style>
.content {
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
}
</style>
leaflet组件,由于render.js中不能使用uni的相关api,也无法获取store中的值,所以通过监听obj对象,调用receiveMsg方法获取请求到的数据
<template>
<view>
<view id="map" :obj="obj" :change:obj="leaflet.receiveMsg"></view>
<view class="control">
<button type="primary" @click="addMarker()">10万点</button>
</view>
</view>
</template>
<script module="leaflet" lang="renderjs">
import L from 'static/js/leaflet.js';
import 'static/js/leaflet.markercluster.js'
import 'static/js/leaflet.canvas-markers.js';//在canvas
export default {
data() {
return {
map:null,
canvasLayer:null,
cluster:null
};
},
mounted() {
this.initMap();
},
methods:{
// 初始化地图
initMap(){
this.map = L.map('map',{
crs: L.CRS.EPSG3857, // 地图投影坐标系
center:[30.67, 104.07],//地图中心经纬度
zoom:17,//当前缩放等级
minZoom:5,//最小缩放等级
maxZoom:18,//最大缩放等级
dragging:true,//是否允许拖拽
attributionControl: false,//是否去除右下角标志
zoomControl:false//是否显示地图缩放图例
});
// 添加图层,天地图影像
L.tileLayer('https://t{s}.tianditu.gov.cn/DataServer?T=img_w&X={x}&Y={y}&L={z}&tk=6d4deb37bf726665d610b256b2d196c5', {
subdomains: ['1', '2', '3', '4', '5', '6', '7']
}).addTo(this.map);
let cluster = new L.MarkerClusterGroup()
this.cluster = cluster
cluster.markers = []
// console.log(this.markers)
this.map.addLayer(cluster)
},
createMarkers(data){
let that=this
if(this.canvasLayer) this.map.removeLayer(this.canvasLayer);
this.canvasLayer = L.canvasIconLayer({}).addTo(this.map);
console.log(48,this.canvasLayer)
data.forEach(item => {
var marker = L.marker([item["latitude"], item["longitude"]], {
icon: L.icon({
iconUrl: "static/images/marker-icon.png",
iconSize: [40, 40],
iconAnchor: [20, 20],
text: item.AQI,
textAnchor: [10, -10],
textFont: '14px bold', //设置字体大小和样式
textFillStyle: '#FFFFFF'
})
}).bindPopup("I Am " + item.cityName);
that.cluster.markers.push(marker)
that.cluster.addLayer(marker)
// that.canvasLayer.addLayer(marker);
});
},
//接受script传递回来的obj,绘制点位
receiveMsg(newValue, oldValue, ownerVm, vm) {
console.log(65,newValue)
if(newValue?.type === "marker"&&newValue?.data.length>0){
this.createMarkers(newValue?.data)
}
},
}
}
</script>
<script>
export default {
data() {
return {
obj: {
type: 'marker',
data: []
},
data: []
};
},
mounted() {},
methods: {
addMarker() {
for (let i = 0; i < 50000; i++) {
let obj = {
latitude: '30.67',
cityName: '成都',
AQI: i,
longitude: '104.07'
};
obj['latitude'] -= (Math.random() * 10).toFixed(2);
obj['longitude'] -= (Math.random() * 10).toFixed(2);
this.data.push(obj);
}
this.obj = { ...this.obj, data: this.data };
}
}
};
</script>
<style lang="scss">
#map {
height: 60vh;
width: 100vw;
}
.control {
width: 100vw;
height: 40vh;
padding: 20rpx;
}
</style>
vue3 下
区别在于vue3下不能采用本地引入leaflet.js,会报leaflet没有默认的导出模块错误,只能通过npm的方式或者在mounted中通过cdn方式动态引入,由于项目需要使用点聚合 ,通过cdn方式引入多个script会报错,所以采用npm
- 监听多个属性
<view
class="mapBox"
id="mapId"
:prop="latlon"
:change:prop="leaflet.getData"
:mapMarkerList="mapMarkerList"
:change:mapMarkerList="leaflet.getMapMarkerList"
:flyLatlon="flyLatlon"
:change:flyLatlon="leaflet.flyToZy"
></view>
注:npm方式引入时,会导致leaflet.js中marker的默认图标路径不可用,得把图片转base64才能用,(H5上可以,打包成app图片裂开)
引入天地图多个底图时可以使用Leaflet.ChineseTmsProviders插件