uniapp中利用renderjs引入leaflet
由于uniapp中要使用地图,虽然uni-app有地图组件map,但是很难用,而且性能很差。在app中是不能操作dom,所以直接用leaflet是不可能的。最终发现了renderjs,官网提出,在app-vue环境下,视图层由webview渲染,而renderjs运行在视图层,自然可以操作dom和window。
使用注意事项:
:prop 传值 :change:prop 监听prop改变
调用改变的方法内有四个参数
newValue:跟新后的数据
oldValue:原先的数据
ownerInstance:通过该函数可以调用内部函数,可以传输数据
instance:当前service层实例
通过 this.$ownerInstance.$vm 获取当前组件的 ComponentDescriptor 实例
完整示例代码:
<template> <view class="leafletMap"> <view class="mapBox" id="mapId" :prop="psArr" :change:prop="leaflet.updatePsArr" ></view> </view> </template> <script> export default { data() { return { psArr: [], //企业数组 }; }, onLoad() { this.$nextTick(() => { this.queryPsGis(); }); }, methods: { //请求企业gis数据 async queryPsGis() { this.psArr = []; //重置企业的站点信息 const { data = {} } = await this.$http( '/smoke/smokeData/getPsRealityDataGis', 'get' ); if (data.code !== 200) { return uni.showToast({ title: '请求数据异常', icon: 'error', mask: true, }); } if (data.result.length > 0) { this.psArr = data.result.filter( (item) => item.pscode !== null && item.pscode !== undefined && item.pscode !== '' ); //排除第一个无意义内容 } }, //renderjs 传递给视图层 getMessage(option) { uni.showToast({ title: option.text, icon: 'success', mask: true, }); }, }, }; </script> <script module="leaflet" lang="renderjs"> export default { data() { return { map: null, //地图容器 centerpoint: [37.6211, 114.9304676], //默认中心位置 zoomlevel: 14, //初始化放大倍数 baseLayer: null, //矢量底图 markers:null, ownerInstance:null,//接收视图层dom } }, mounted() { // 动态引入较大类库避免影响页面展示 const link = document.createElement('link'); link.rel = "stylesheet" link.href = "https://unpkg.com/leaflet@1.9.3/dist/leaflet.css"; document.head.appendChild(link) const script = document.createElement('script') script.src = "https://unpkg.com/leaflet@1.9.3/dist/leaflet.js" script.type = "text/javascript" script.onload = this.initMap.bind(this) document.head.appendChild(script) }, methods: { initMap() { this.map = L.map('mapId', { minZoom: 5, maxZoom: 18, crs: L.CRS.EPSG3857, center: this.centerpoint, zoom: this.zoomlevel, fullscreenControl: false, zoomControl: false, attributionControl: false, }) //添加基础图层 this.baseLayer = L.tileLayer( 'http://map.geoq.cn/ArcGIS/rest/services/ChinaOnlineCommunity/MapServer/tile/{z}/{y}/{x}', { minZoom: 5, maxZoom: 18, pane: 'overlayPane', } ) this.map.addLayer(this.baseLayer) }, //属性psArr变化监控 updatePsArr(newValue, oldValue, ownerInstance, instance) { if(newValue.length>0){ this.ownerInstance = ownerInstance if(this.markers){ this.map.removeLayer(this.markers) this.markers = null } this.addMarkerCluster(newValue) } }, //处理整合geoJSON所需要的marker数据 handlePsGeoJson(arr) { let coorsField = { type: 'FeatureCollection', features: [], } arr.forEach((item) => { let lon = item.lon let lat = item.lat if (lon && lat) { coorsField.features.push({ type: 'Feature', properties: {}, geometry: { type: 'Point', // 配合 pointToLayer 一起使用 coordinates: [lon, lat], }, }) } }) return coorsField }, //添加marker标记 addMarkerCluster(arr) { // 添加站点marker标记 this.markers = L.geoJSON(this.handlePsGeoJson(arr), { pointToLayer: (feature, latlng) => { return L.marker(latlng, { icon: this.getMarkerIcon(), zIndexOffset: 1000 }) // 添加标记 }, }) this.map.fitBounds(this.markers.getBounds()) this.markers.addTo(this.map) //renderjs传递给视图层 // this.ownerInstance.callMethod('getMessage', { // text: '成功' // }) }, getMarkerIcon() { let htmlContent = '<div style="width:24px;height:24px;border-radius:50%;background-color:#5ed323"></div>' let icon = L.divIcon({ html: htmlContent, className: 'ss', iconAnchor: [13, 4], }) return icon } } } </script> <style lang="scss" scoped> .leafletMap { width: 100%; height: 100%; .mapBox { box-sizing: border-box; width: 100%; height: 100vh; background-color: #042046; overflow: hidden; } } </style>