Files
dvcp_v2_webapp/ui/packages/tools/AiTMap.vue
2022-12-01 09:35:20 +08:00

157 lines
4.2 KiB
Vue

<template>
<section class="AiTMap">
<div ref="tmap" class="map"/>
</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
}
},
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() {
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, 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 mapLib.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;
:deep(.map ){
height: 100%;
& > div > div {
&:nth-of-type(2), &:nth-of-type(3) {
display: none;
}
}
}
}
</style>