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