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>
 |