157 lines
		
	
	
		
			4.2 KiB
		
	
	
	
		
			Vue
		
	
	
	
	
	
			
		
		
	
	
			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>
 |