<script lang="ts" setup> import { onMounted, ref } from 'vue' import AMapLoader from '@amap/amap-jsapi-loader' import dogUrl from '../../assets/tempImages/dog.png' import markerUrl from '../../assets/marker/marker.png' const props = defineProps({ patrolInfoList: Array as any, }) // 定义巡航点的 GPS 坐标 const cruisePoints: any = ref([]) const mapContainer = ref<HTMLDivElement | null>(null) const map: any = ref(null) // 地图实例 const markerLayer = ref<AMap.OverlayGroup | null>(null) const dogLayer = ref<AMap.OverlayGroup | null>(null) const dogMarker = ref<AMap.Marker | null>(null) const dogMarkerPosition = ref() // 狗的当前位置 // 初始化地图 const initMap = async () => { if (!mapContainer.value) { return } console.log('aMapIndex: aMapSecret', window.localStorage.getItem('aMapSecret')) console.log('aMapIndex: aMapKey', window.localStorage.getItem('aMapKey')) try { if (!window._AMapSecurityConfig) { // 安全码 window._AMapSecurityConfig = { securityJsCode: window.localStorage.getItem('aMapSecret'), } } // 加载高德地图 API const AMap = await AMapLoader.load({ key: window.localStorage.getItem('aMapKey')!, // 替换为你的高德地图 API Key version: '2.0', plugins: ['AMap.Scale', 'AMap.MoveAnimation'], }) // 创建地图实例 map.value = new AMap.Map(mapContainer.value, { zoom: 18, center: [116.397428, 39.90923], viewMode: '2D', // 地图模式 }) console.log('map实例', map.value) } catch (error) { console.error('Failed to load AMap API:', error) return null } } // ----------------------------------------marker----------------------------------------------- // 移除标记图层 const removeMarkerLayer = () => { if (map.value && markerLayer.value) { map.value.remove(markerLayer.value) markerLayer.value = null } } // 创建巡航点标记 const createMarkers = () => { if (!map.value) { return } removeMarkerLayer() const markers: AMap.Marker[] = [] // 创建marker图层 if (!markerLayer.value) { markerLayer.value = new AMap.OverlayGroup() } cruisePoints.value.forEach((item: any, index: number) => { let labelText = '' if (index === 0) { labelText = '起' } else if (index === cruisePoints.value.length - 1) { labelText = '终' } else { labelText = `${index + 1}` } // 自定义标记内容 // const markerContent = ` // <div class="custom-marker" style=" // width: 30px; // height: 30px; // background-color: #0d76d4; // border-radius: 50%; // color: white; // text-align: center; // line-height: 30px; // box-shadow: 0 0 8px rgba(0, 0, 0, 0.3); // transition: transform 0.3s ease; // "> // ${labelText} // </div> // ` const markerContent = ` <div style="width: 40px; height: 40px; position: relative; display: flex; justify-content: center;"> <img src="${markerUrl}" style="width: 100%; height: 100%; object-fit: cover;"> <span style="position: absolute; color: #fff; font-size: 13px;padding-top: 4px;font-weight: 600;">${labelText}</span> </div> ` const marker = new AMap.Marker({ position: item.point, content: markerContent, offset: new AMap.Pixel(-15, -15), // 调整标记的偏移量,使其居中显示 }) const content = '<div style="font-size: 16px;padding: 6px"> <div style="font-weight: bold;padding-bottom: 10px">巡检点信息</div>' + `<div style="font-size: 14px;padding-bottom: 6px"><label style="font-weight: bold;padding-right: 16px">巡检路线:</label>${item.routeName}</div>` + `<div style="font-size: 14px;padding-bottom: 6px"><label style="font-weight: bold;padding-right: 16px">小区名称:</label>${item.communityName}</div>` + `<div style="font-size: 14px;padding-bottom: 6px"><label style="font-weight: bold;padding-right: 16px">小区地址:</label>${item.communityAddress}</div>` + `<div style="font-size: 14px;padding-bottom: 6px"><label style="font-weight: bold;padding-right: 16px">点位编号:</label>${item.routeNumber}</div>` + `<div style="font-size: 14px;padding-bottom: 6px"><label style="font-weight: bold;padding-right: 16px">位ㅤㅤ置:</label>${item.gpsX}, ${item.gpsY}</div>` + '</div>' // 创建 InfoWindow 并设置内容 const infoWindow = new AMap.InfoWindow({ content, offset: new AMap.Pixel(0, -30), }) // 绑定点击事件,点击 marker 显示 InfoWindow marker.on('click', () => { infoWindow.open(map.value, marker.getPosition()) }) // map.value.setView(cruisePoints.value[cruisePoints.value.length - 1].point) markers.push(marker) markerLayer.value.addOverlay(marker) map.value.setFitView(markers) }) map.value.add(markerLayer) return markers } // 创建连线 const createPolylines = () => { if (!map.value || !markerLayer.value) { return } for (let i = 1; i < cruisePoints.value.length; i++) { const polyline = new AMap.Polyline({ path: [cruisePoints.value[i - 1].point, cruisePoints.value[i].point], strokeColor: '#FF33FF', strokeWeight: 2, strokeOpacity: 1, lineJoin: 'round', lineCap: 'round', zIndex: 50, }) markerLayer.value.addOverlay(polyline) } } // 创建标记和连线并添加到图层 const createMarkersAndPolylines = () => { if (!map.value) { return } markerLayer.value = new AMap.OverlayGroup() createMarkers() createPolylines() map.value.add(markerLayer.value) } // --------------------------------------------dog------------------------------------------------ // 移除狗图层 const removeDogLayer = () => { if (map.value && dogLayer.value) { map.value.remove(dogLayer.value) dogLayer.value = null } } // 创建移动标记并添加到 dogLayer 图层 const createDogMarker = () => { if (!map.value) { return } // 创建 dogLayer 图层 dogLayer.value = new AMap.OverlayGroup() map.value.add(dogLayer.value) const movingMarkerContent = ` <div style="width: 50px; height: 50px;"> <img src="${dogUrl}" style="width: 100%; height: 100%; object-fit: cover;"> </div> ` const movingMarker = new AMap.Marker({ position: cruisePoints.value[0].point, content: movingMarkerContent, offset: new AMap.Pixel(-15, -15), }) dogMarkerPosition.value = cruisePoints.value[0].point dogLayer.value.addOverlay(movingMarker) dogMarker.value = movingMarker } // 开始移动标记 const startMoving = (e: any, endPoint: string[]) => { if (!dogMarker.value) { console.error('移动标记不存在') return } console.log('点击开始移动', cruisePoints.value) if (map.value && dogLayer.value && dogMarker.value) { const path = [dogMarkerPosition.value, endPoint] console.log('移动路径', path) dogMarker.value.moveAlong(path, { // speed: 10000, // 移动速度为 x米/秒 loop: false, // 不循环移动 duration: window.localStorage.getItem('dogWalkTime') || 2000, // 动画时长 autoRotation: false, // 标记根据移动方向自动旋转 }) dogMarkerPosition.value = endPoint } } // ----------------------------------------------------------------------------------------------- watch(() => props.patrolInfoList, async (newVal) => { console.log('监听到巡检点变化', newVal) if (!map.value) { await initMap() } if (Array.isArray(newVal) && newVal.length) { cruisePoints.value = newVal.map((item: any) => { return { ...item, point: [Number(item.gpsX), Number(item.gpsY)], } }) createMarkersAndPolylines() } }, { deep: true, immediate: true }) onMounted(async () => { await initMap() }) // ----------------------- 以下是暴露的方法内容 ---------------------------- defineExpose({ createMarkers, createPolylines, removeMarkerLayer, createDogMarker, startMoving }) </script> <template> <div ref="mapContainer" style="width: 100%; height: 500px;" /> </template>