236 lines
5.9 KiB
Vue
236 lines
5.9 KiB
Vue
<template>
|
|
<section class="AiTMap">
|
|
<div ref="tmap" class="map"/>
|
|
<div class="mapLayerSwitcher" flex>
|
|
<div class="item" :class="{current:mapType=='vector'}" @click="mapType='vector'"/>
|
|
<div class="item satellite" :class="{current:mapType=='satellite'}" @click="mapType='satellite'"/>
|
|
</div>
|
|
</section>
|
|
</template>
|
|
|
|
<script>
|
|
|
|
export default {
|
|
name: "AiTMap",
|
|
props: {
|
|
/**
|
|
* 地区id
|
|
*/
|
|
areaId: String,
|
|
/**
|
|
* 地图参数,详情见https://lbs.qq.com/webApi/javascriptGL/glDoc/docIndexMap
|
|
*/
|
|
ops: {default: () => ({})},
|
|
/**
|
|
* 加载三方库,以腾讯地图文档要求进行添加
|
|
*/
|
|
libraries: {default: () => ["service"]},
|
|
/**
|
|
* 地图实例,支持用.sync绑定获取
|
|
*/
|
|
map: Object,
|
|
/**
|
|
* 地图库,支持用.sync绑定获取
|
|
*/
|
|
lib: Object,
|
|
},
|
|
data() {
|
|
return {
|
|
tmap: null,
|
|
mapLib: null,
|
|
mapType: 'vector'
|
|
}
|
|
},
|
|
watch: {
|
|
mapType(type) {
|
|
this.tmap?.setBaseMap({type})
|
|
}
|
|
},
|
|
computed: {
|
|
key() {
|
|
return process.env.NODE_ENV == "production" ?
|
|
"RWWBZ-64BEJ-MVLFJ-FTHLQ-JTR6J-SAB2S" :
|
|
"3RZBZ-LZUCF-CT6J5-NWKZH-FCWOQ-UUFKY"
|
|
}
|
|
},
|
|
methods: {
|
|
injectLib(url, cb) {
|
|
const script = document.createElement('script')
|
|
script.type = 'text/javascript';
|
|
script.id = "aitmap";
|
|
script.src = url;
|
|
script.addEventListener('load', () => {
|
|
cb && cb()
|
|
})
|
|
document.body.appendChild(script);
|
|
},
|
|
initTMap() {
|
|
const TMap = window?.TMap
|
|
this.mapLib = TMap
|
|
this.tmap = new TMap.Map(this.$refs.tmap, {
|
|
zoom: 11,
|
|
...this.ops
|
|
})
|
|
this.$emit('loaded')
|
|
this.$emit('update:lib', TMap)
|
|
this.$emit('update:map', this.tmap)
|
|
this.areaId && this.getMapArea()
|
|
},
|
|
getMapArea() {
|
|
let {mapLib: TMap, areaId, tmap: map} = this, keyword = areaId.substring(0, 6)
|
|
const fitBounds = (latLngList) => {
|
|
// 由多边形顶点坐标数组计算能完整呈现该多边形的最小矩形范围
|
|
if (latLngList.length === 0) {
|
|
return null;
|
|
}
|
|
let boundsN = latLngList[0].getLat();
|
|
let boundsS = boundsN;
|
|
let boundsW = latLngList[0].getLng();
|
|
let boundsE = boundsW;
|
|
latLngList.forEach((point) => {
|
|
point.getLat() > boundsN && (boundsN = point.getLat());
|
|
point.getLat() < boundsS && (boundsS = point.getLat());
|
|
point.getLng() > boundsE && (boundsE = point.getLng());
|
|
point.getLng() < boundsW && (boundsW = point.getLng());
|
|
});
|
|
return new TMap.LatLngBounds(
|
|
new TMap.LatLng(boundsS, boundsW),
|
|
new TMap.LatLng(boundsN, boundsE)
|
|
);
|
|
}
|
|
let polygons = new TMap.MultiPolygon({map, geometries: []});
|
|
new TMap.service.District({
|
|
polygon: 2,
|
|
maxOffset: 100
|
|
}).search({keyword}).then(res => {
|
|
if (res?.result) {
|
|
let center = res.result?.[0]?.[0]?.location
|
|
this.tmap.setCenter(center)
|
|
res.result.forEach((level) => {
|
|
level.forEach((place) => {
|
|
let bounds = [];
|
|
let newGeometries = place.polygon.map((polygon, index) => {
|
|
bounds.push(fitBounds(polygon)); // 计算能完整呈现行政区边界的最小矩形范围
|
|
return {
|
|
id: `${place.id}_${index}`,
|
|
paths: polygon, // 将得到的行政区划边界用多边形标注在地图上
|
|
};
|
|
});
|
|
bounds = bounds.reduce((a, b) => {
|
|
return fitBounds([
|
|
a.getNorthEast(),
|
|
a.getSouthWest(),
|
|
b.getNorthEast(),
|
|
b.getSouthWest(),
|
|
]);
|
|
}); // 若一行政区有多个多边形边界,应计算能包含所有多边形边界的范围。
|
|
polygons.updateGeometries(newGeometries);
|
|
this.tmap.fitBounds(bounds);
|
|
});
|
|
});
|
|
}
|
|
})
|
|
}
|
|
},
|
|
mounted() {
|
|
if (!window?.TMap) {
|
|
window.initTMap = this.initTMap
|
|
this.injectLib(`https://map.qq.com/api/gljs?v=1.exp&key=${this.key}&libraries=${this.libraries.toString()}&callback=initTMap`)
|
|
} else {
|
|
this.initTMap()
|
|
}
|
|
},
|
|
destroyed() {
|
|
this.map?.destroy()
|
|
}
|
|
}
|
|
</script>
|
|
|
|
<style lang="scss" scoped>
|
|
.AiTMap {
|
|
width: 100%;
|
|
height: 100%;
|
|
flex: 1;
|
|
min-width: 0;
|
|
min-height: 0;
|
|
position: relative;
|
|
|
|
:deep(.map ) {
|
|
height: 100%;
|
|
|
|
& > div > div {
|
|
&:nth-of-type(2), &:nth-of-type(3) {
|
|
display: none;
|
|
}
|
|
}
|
|
}
|
|
|
|
.mapLayerSwitcher {
|
|
position: absolute;
|
|
z-index: 202304061607;
|
|
bottom: 20px;
|
|
right: 12px;
|
|
background-color: #fff;
|
|
padding: 5px;
|
|
width: fit-content;
|
|
height: 56px;
|
|
box-sizing: content-box;
|
|
overflow: hidden;
|
|
transition: width 2s ease;
|
|
gap: 10px;
|
|
|
|
&:hover {
|
|
.item {
|
|
display: block;
|
|
}
|
|
}
|
|
|
|
.item {
|
|
position: relative;
|
|
width: 80px;
|
|
height: 56px;
|
|
border: 1px dashed #ddd;
|
|
cursor: pointer;
|
|
flex-shrink: 0;
|
|
background-image: url("https://cdn.cunwuyun.cn/map/defaultMap.png");
|
|
box-sizing: border-box;
|
|
color: #fff;
|
|
background-size: 100%;
|
|
display: none;
|
|
|
|
&.current {
|
|
border: 1px solid #366FFF;
|
|
display: block !important;
|
|
|
|
&:before {
|
|
background-color: #366FFF;
|
|
}
|
|
}
|
|
|
|
&:hover {
|
|
border-color: #333;
|
|
}
|
|
|
|
&:before {
|
|
font-size: 12px;
|
|
line-height: 18px;
|
|
padding: 0 3px;
|
|
position: absolute;
|
|
bottom: 0;
|
|
right: 0;
|
|
content: "地图";
|
|
user-select: none;
|
|
}
|
|
|
|
&.satellite {
|
|
background-image: url("https://cdn.cunwuyun.cn/map/satelliteMap.png");
|
|
|
|
&:before {
|
|
content: "卫星"
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
</style>
|