Files
dvcp_v2_webapp/ui/packages/tools/AiQMap.vue

314 lines
7.8 KiB
Vue
Raw Normal View History

<template>
<section class="AiTMap">
<div ref="tmap" class="map"/>
</section>
</template>
<script>
export default {
name: 'AiQMap',
props: {
areaId: String,
ops: {
default: () => {
return {}
}
},
libraries: {
default: () => ['service']
},
markerIcon: {
type: String
},
is3dAround: {
type: Boolean,
default: false
},
is3d: {
type: Boolean,
default: false
},
limitArea: {
type: Boolean,
default: false
},
map: Object,
lib: Object,
markers: {
type: Array,
default: () => []
}
},
watch: {
markers: {
handler (v) {
if (window.TMap && v.length) {
this.addMarkers(v)
}
},
deep: true,
immediate: true
}
},
data () {
return {
tmap: null,
mapLib: null,
marker: null,
keyframe: [
{
percentage: 0,
rotation: 0
},
{
percentage: 0.2,
rotation: 72
},
{
percentage: 0.4,
rotation: 144
},
{
percentage: 0.6,
rotation: 216
},
{
percentage: 0.8,
rotation: 288
},
{
percentage: 1,
rotation: 360
}
]
}
},
computed: {
key () {
return process.env.NODE_ENV == 'production' ? 'RWWBZ-64BEJ-MVLFJ-FTHLQ-JTR6J-SAB2S' : '3RZBZ-LZUCF-CT6J5-NWKZH-FCWOQ-UUFKY'
}
},
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()
}
},
methods: {
injectLib (url, cb) {
const script = document.createElement('script')
script.type = 'text/javascript'
script.id = 'aiqmap'
script.src = url
script.addEventListener('load', () => {
cb && cb()
})
document.body.appendChild(script)
},
setMarkersCenter () {
var bounds = new TMap.LatLngBounds()
this.markers.forEach(item => {
if (bounds.isEmpty() || !bounds.contains(new TMap.LatLng(item.lat, item.lng))) {
bounds.extend(new TMap.LatLng(item.lat, item.lng))
}
})
this.tmap.fitBounds(bounds, {
padding: 100
})
},
addMarkers (v) {
if (this.marker) {
this.marker.setMap(null)
}
this.marker = new TMap.MultiMarker({
id: 'markers',
map: this.tmap,
styles: {
marker: new TMap.MarkerStyle({
width: 25,
height: 35,
color: '#333',
size: 16,
offset: { x: 0, y: 8 },
anchor: { x: 17, y: 23 },
direction: 'bottom',
strokeWidth: 2,
src: this.markerIcon
})
},
geometries: v.map(v => {
return {
...v,
styleId: 'marker',
position: new TMap.LatLng(v.lat, v.lng)
}
})
})
this.setMarkersCenter()
this.marker.on('click', e => {
this.$emit('markerClick', e.geometry)
})
},
initTMap () {
this.mapLib = TMap
this.tmap = new TMap.Map(this.$refs.tmap, {
zoom: 11,
...this.ops,
viewMode: this.is3d ? '3d' : '2d',
pitch: this.is3d ? 40 : 0,
// mapStyleId: 'style1',
baseMap: this.limitArea ? [
{ type: 'vector', features: ['base'] },
{
type: 'traffic',
opacity: 1,
}
] : [
{ type: 'vector' },
],
renderOptions: {
enableBloom: true, // 是否启用泛光效果 注为true才会有效果
}
})
this.tmap.on('click', e => {
this.$emit('click', e)
})
if (this.markers.length) {
this.addMarkers(this.markers)
}
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)
)
}
if (!this.limitArea) return
let polygons = new TMap.MultiPolygon({map, geometries: []})
new mapLib.service.District({
polygon: 2,
maxOffset: 100
}).search({keyword}).then(res => {
if (res?.result) {
console.log(res.result[0][0].polygon)
let center = res.result[0][0].location
this.tmap.enableAreaHighlight({
paths: res.result[0][0].polygon,
highlightColor: 'rgba(0,0,0,0)',
shadeColor: 'rgba(0,0,0,1)'
})
this.tmap.setCenter(center)
new TMap.MultiPolyline({
map: this.tmap,
styles: {
polyline: new TMap.PolylineStyle({
color: '#017cf7', // 线条填充色,
width: 8,
lineCap: 'round',
enableBloom: true, // 是否启用泛光 注为true才会有效果
}),
},
geometries: [
{
styleId: 'polyline', // 样式id
paths: res.result[0][0].polygon
}
]
})
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)
})
})
setTimeout(() => {
this.is3dAround && this.tmap.startAnimation(this.keyframe, {
duration: 16000,
loop: Infinity
})
}, 600)
}
})
}
},
destroyed () {
this.tmap.destroy()
}
}
</script>
<style lang="scss" scoped>
.AiTMap {
width: 100%;
height: 100%;
flex: 1;
min-width: 0;
min-height: 0;
2022-12-01 09:35:20 +08:00
:deep(.map ){
height: 100%;
& > div > div {
&:nth-of-type(2), &:nth-of-type(3) {
display: none;
}
}
}
}
</style>