314 lines
7.8 KiB
Vue
314 lines
7.8 KiB
Vue
<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;
|
||
|
||
:deep(.map ){
|
||
height: 100%;
|
||
|
||
& > div > div {
|
||
&:nth-of-type(2), &:nth-of-type(3) {
|
||
display: none;
|
||
}
|
||
}
|
||
}
|
||
}
|
||
</style>
|