使用天地图---appp端
依靠leaflet和uniapp中的renderjs来渲染天地图
1.下载依赖:cnpm i leaflet
2.下载依赖:cnpm i leaflet.chinamsproviders
一.Dom结构:
<view>
<view class="mapBox" id="mapId" :prop="markerArr" :change:prop="leaflet.updatePsArr" :prop='marker2' :change:prop="leaflet.updatePsArr2" ...></view>
<view @click="leaflet.emitData"></view>
</view>
<script>
//调接口在普通script中,然后传递给视图层
...
method:{
receiveRenderData(val){
console.log('视图层传递的值',val)
}
}
</script>
<script module="leaflet" lang="renderjs">
//拿到逻辑层接口返回的数据进行渲染
export default{
data(){},
method:{
//dom结构,点击事件触发
emitData(e, ownerVm){
ownerVm.callMethod('receiveRenderData', '视图层传递至逻辑层')
},
//renderjs中触发
}
}
<script>
ps:
1.prop绑定的是renderjs所监听的数据
2.change:prop所绑定的是renderjs中的module的属性值+'.'+方法名
renderjs中:
updatePsArr(newValue, oldValue, ownerInstance, instance){
console.log('所监听的值',newValue)
}
3.视图层(renderjs)传递数据给逻辑层(普通script标签):
this_.$ownerInstance.callMethod('逻辑层中的method方法',参数1,参数2...)
二.开始使用leaflet天地图
<template>
<view class="leafletMap">
<view class="mapBox" id="mapId" :prop="markerArr" :change:prop="leaflet.updatePsArr"></view>
<view class="headerMenu" :style="{top:`${headerMenuToppx}px`}">
<view class="avatar">
<text>{{ realName }}</text>
</view>
<view class="selectItem">
<uni-data-select v-model="selectItem" :localdata="selectItemArr" @change="changeSelectItem">
</uni-data-select>
</view>
<view class="reset">
<!-- <img src="@/static/index/reset.png" alt="" class="resetImg"> -->
<image src="@/static/index/reset.png" mode="" class="resetImg"></image>
</view>
</view>
<view class="bachInitCenter" @click="leaflet.backInitCenterFn">
<!-- <img src="@/static/index/backInitCenter.png" alt="" class="backInitImg"> -->
<image src="@/static/index/backInitCenter.png" mode="" class="backInitImg"></image>
</view>
<!-- <div class="rw_point1"><img src="@/static/logo/rw_point1.png" alt=""></div>
<div class="rw_point2"><img src="@/static/logo/rw_point2.png" alt=""></div>
<div class="rw_point3"><img src="@/static/logo/rw_point3.png" alt=""></div>
<div class="rw_point4"><img src="@/static/logo/rw_point4.png" alt=""></div>
<div class="rw_point5"><img src="@/static/logo/rw_point5.png" alt=""></div> -->
</view>
</template>
<script>
import {
indexSelect,
listArr
} from "@/api/api.js";
export default {
data() {
return {
selectItem: "", //下拉选择项--展示的文字
selectItemArr: [], //下拉选项数组
markerArr: [], //地图上的点位数组
headerMenuToppx: 0, //状态栏高度
};
},
computed: {
realName() {
// if (uni.getStorageSync('realname')) {
// return uni.getStorageSync('realname').substr(-1)
// }
}
},
onLoad() {
uni.getSystemInfo({
success: (res) => {
this.headerMenuToppx = res.statusBarHeight
}
})
},
mounted() {
this.selectItemFn()
},
methods: {
//renderjs 传递给视图层
getMessage(option) {
uni.showToast({
title: option.text,
icon: 'success',
mask: true,
});
},
selectItemFn() {
indexSelect({}).then(res => {
this.selectItemArr = res.data.result.map((item, index) => {
return {
text: item.name,
value: item.id,
disable: false
}
})
let e = this.selectItemArr[0].value
this.selectItem = e
this.markerFn(e)
})
},
markerFn(id) {
console.log('重新请求接口',id)
listArr({
projectId: id
}).then(res => {
let _markerArr = JSON.parse(JSON.stringify(res.data.result))
this.markerArr = _markerArr
})
},
changeSelectItem(e) {
this.selectItem = e
this.markerFn(e)
},
},
};
</script>
<script module="leaflet" lang="renderjs">
import jxJson from '@/static/jxJson/jxJson.json';
export default {
data() {
return {
map: null, //地图容器
centerpoint: [37.6211, 114.9304676], //默认中心位置
ownerInstance: null, //接收视图层dom
myGroup:{},//清空map上的点位
}
},
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"
document.head.appendChild(script)
script.onload = this.initMap.bind(this)
},
methods: {
//初始化地图
initMap() {
//底图
const image = L.tileLayer(
'http://t{s}.tianditu.gov.cn/img_w/wmts?tk=cb59b14d0b2d8f29c32ea8118cd5cebb&SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TileMatrix={z}&TileCol={x}&TileRow={y}', {
subdomains: [0, 1, 2, 3, 4, 5, 6, 7],
})
//注记
const cia = L.tileLayer(
'http://t{s}.tianditu.gov.cn/cia_w/wmts?tk=cb59b14d0b2d8f29c32ea8118cd5cebb&SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TileMatrix={z}&TileCol={x}&TileRow={y}', {
subdomains: [0, 1, 2, 3, 4, 5, 6, 7],
transparent: true,
zIndex: 3,
})
//天地图图组
const tiandiMap = L.layerGroup([image, cia]);
//地图对象
this.map = L.map('mapId', {
crs: L.CRS.EPSG3857,
center: [27.682976, 115.857972],
maxZoom: 18,
zoom: 7,
minZoom: 2,
attributionControl: false,
layers: [tiandiMap],
zoomControl: false
});
image.addTo(this.map)
cia.addTo(this.map)
//江西省边界线
L.geoJSON(jxJson, {
"color": "blue",
"weight": 3,
"opacity": 0.4,
"fillColor": "transparent",
"fillOpacity": 0
}).addTo(this.map)
//遮罩层函数
this.featureFn()
},
//遮罩层函数
featureFn() {
//遮罩层遮蔽层,geojson分两种情况
var latlngs;
var feature = jxJson["features"][0].geometry.coordinates
if (feature[0][0][0] instanceof Array) {
latlngs = feature[0]
} else {
latlngs = feature
}
var pNW = {
lat: 59.0,
lng: 73.0
};
var pNE = {
lat: 59.0,
lng: 136.0
};
var pSE = {
lat: 3.0,
lng: 136.0
};
var pSW = {
lat: 3.0,
lng: 73.0
};
//向数组中添加一次闭合多边形,并将西北角再加一次作为之后画闭合区域的起点
var pArray = [];
pArray.push(pNW);
pArray.push(pSW);
pArray.push(pSE);
pArray.push(pNE);
pArray.push(pNW);
//循环添加各闭合区域
for (var i = 0; i < latlngs.length; i++) {
var points = [];
for (let j = 0; j < latlngs[i].length; j++) {
points.push({
lat: Number(latlngs[i][j][1]),
lng: Number(latlngs[i][j][0])
});
}
//将闭合区域加到遮蔽层上,每次添加完后要再加一次西北角作为下次添加的起点和最后一次的终点
pArray = pArray.concat(points);
pArray.push(pArray[0]);
}
//反向遮蔽层
let ahLayer = L.polygon(pArray, {
color: 'transparent',
fillColor: '#ebf0f6',
fillOpacity: 0.6,
renderer: L.canvas({
padding: 1
}) //解决遮罩层拖拽与缩放显示不全的Bug
}); //建立多边形覆盖物
ahLayer.addTo(this.map);
},
//属性psArr变化监控
updatePsArr(newValue, oldValue, ownerInstance, instance) {
if (newValue) {
this.markerFn(newValue)
}
},
markerFn(newValue){
let _that = this
if(Object.keys(this.myGroup).length){
this.myGroup.clearLayers()
}
this.map.clearLayers()
setTimeout(function() {
/*
循环一个一个加
*/
// let layers = []
// let marker
// newValue.forEach(item => {
// let markerIcon = L.icon({
// iconUrl: `https://www.jxdkchy.com:27705/markerImg/rw_point${item.missionStatus}.png`,
// iconSize: [20,25]
// })
// marker = L.marker([_that.checkLat(item.lat), _that.checkLon(item.lon)], {
// icon: markerIcon,
// data: item
// })
// layers.push(marker)
// // marker.addTo(_that.map)
// })
// let layerGroup = L.layerGroup(layers)
// this.map.addLayer(layerGroup)
/*
分组添加marker
*/
let layers = []
for(let i = 0; i < newValue.length; i++){
let markerIcon = L.icon({
iconUrl: `https://www.jxdkchy.com:27705/markerImg/rw_point${newValue[i].missionStatus}.png`,
iconSize: [20,25]
})
let layer = new L.marker([_that.checkLat(newValue[i].lat), _that.checkLon(newValue[i].lon)],{
icon:markerIcon,
data:newValue[i]
})
layers.push(layer)
}
let myGroup = L.layerGroup(layers)
_that.map.addLayer(myGroup)
_that.myGroup = myGroup // 下次清空点位要用,告诉地图清空哪些
}, 0);
},
//坐标六十进制转为十进制
checkLon(lon) {
let result = lon
let index = lon.indexOf('.')
if (index > 4) {
let h = lon.substring(0, 3) * 1
let m = lon.substring(3, 5) / 60
let s = lon.substring(5) / 3600
let digital = h + m + s
result = digital.toFixed(8)
} else if (index === -1) {
if (lon.indexOf('°') !== -1) {
let h = lon.substring(0, 3) * 1
let m = lon.substring(4, 6) / 60
let s = lon.substring(7, 9) / 3600
let digital = h + m + s
result = digital.toFixed(8)
}
// this.$notification.error({
// message: '格式不正确!',
// description: '请输入正确格式的坐标!',
// })
}
return result
},
checkLat(lat) {
let result = lat
let index = lat.indexOf('.')
if (index > 4) {
let h = lat.substring(0, 2) * 1
let m = lat.substring(2, 4) / 60
let s = lat.substring(4) / 3600
let digital = h + m + s
result = digital.toFixed(8)
} else if (index === -1) {
if (lat.indexOf('°') !== -1) {
let h = lat.substring(0, 2) * 1
let m = lat.substring(3, 5) / 60
let s = lat.substring(6, 8) / 3600
let digital = h + m + s
result = digital.toFixed(8)
}
}
return result
},
//回到初始位置
backInitCenterFn() {
this.map.panTo([27.682976, 115.857972])
}
}
}
</script>
<style lang="scss" scoped>
.leafletMap {
width: 100%;
height: 100%;
position: relative;
.mapBox {
box-sizing: border-box;
width: 100%;
height: 100vh;
background-color: #042046;
overflow: hidden;
z-index: 0;
}
.headerMenu {
width: 90%;
height: 80rpx;
line-height: 80rpx;
display: flex;
flex-direction: row;
position: absolute;
top: 80rpx;
left: 50%;
margin-left: -45%;
background: #ffffff;
border-radius: 80rpx;
.avatar {
width: 80rpx;
height: 80rpx;
line-height: 80rpx;
background: #1c95ff;
border-radius: 50%;
text-align: center;
color: #fff;
}
.selectItem {
flex: 1;
height: 100%;
.uni-stat__select {
height: 100%;
}
}
.reset {
width: 80rpx;
height: 80rpx;
line-height: 80rpx;
.resetImg {
width: 100%;
height: 100%;
}
}
}
.bachInitCenter {
position: absolute;
bottom: 20rpx;
left: 20rpx;
width: 50rpx;
height: 50rpx;
line-height: 50rpx;
text-align: center;
z-index: 9999;
background: #ffffff;
border-radius: 50%;
overflow: hidden;
.backInitImg {
width: 100%;
height: 100%;
display: block;
}
}
}
</style>
leaflet官网
阿里云数据可视化平台下载江西Json文件