<!-- 地图 --> <script lang="ts" name="Map" setup> import { load } from '@amap/amap-jsapi-loader' import infoDialog from './infoDialog.vue' import useMapStore from '@/store/modules/map' const props = defineProps({ center: { // 地图中心点 type: Array, default: () => ([116.26759100, 39.91563500]), }, zoom: { // 地图显示的缩放级别 type: Number, default: 17, }, // 坐标点数组(包含左边点信息) // 例:[{alarmCode: "XJBJ202310300067",lat: "39.914083",log: "116.265872",icon: ""}] // 必须含有坐标点数据icon // point: { // type: Array, // default: () => ([] as any[]), // }, }) const mapInfo = useMapStore() // 地图信息 const isMap = ref(false) // 是否初始话完成 declare const window: any const map = ref() // 地图实例 const AMapRef = ref<any>() const infoWindow = ref() // 信息窗体 const windowInfoRef = ref() // 信息窗体实例 const markerList = ref<any[]>([]) // 标记点实例 const lineMarkerList = ref<any[]>([]) // 折线标记点实例 const lineList = ref<any>() // 标记点实例 const initMap = () => { // 初始化 if (!window._AMapSecurityConfig) { // 安全码 window._AMapSecurityConfig = { securityJsCode: mapInfo.amapSecurityCode, } } load({ key: mapInfo.amapKey, // 秘钥 version: '2.0', // api版本,2.0 }).then((AMap: any) => { AMapRef.value = AMap map.value = new AMap.Map('container', { zoom: props.zoom, // 设置地图显示的缩放级别 center: props.center, // 设置地图中心点坐标 // layers: [new AMap.TileLayer.Satellite()], //设置图层,可设置成包含一个或多个图层的数组 // mapStyle: 'amap://styles/whitesmoke', //设置地图的显示样式 viewMode: '2D', // 设置地图模式 }) let toolbar AMap.plugin('AMap.ToolBar', () => { // 异步加载插件 toolbar = new AMap.ToolBar() // 缩放工具条实例化 map.value.addControl(toolbar) }) // if (props.center?.length) { // const marker = new AMap.Marker({ // 标注 // position: props.center, // 位置 // }) // map.value.add(marker) // 标注添加到地图 // } isMap.value = true }) } // 根据经纬度查询位置信息 // const searchPosition = (position: any[]) => { // new (AMapRef.value).plugin('AMap.Geocoder', () => { // const geocoder = new map.Geocoder({ // // city 指定进行编码查询的城市,支持传入城市名、adcode 和 citycode // city: '028', // 成都 // }) // geocoder.getAddress(position, (status, result) => { // if (status === 'complete' && result.info === 'OK') { // // result为对应的地理位置详细信息 // this.place = result.regeocode.formattedAddress // // this.place为返回的具体地理位置信息,里面无法使用return回来! // } // }) // }) // } onMounted(() => { if (!map.value) { console.log('地图初始化') initMap() } }) // 绘制标记点 const drawPonit = (arr: any[]) => { // arr 为标记点数组信息数据 // 坐标点数组(包含左边点信息) // 例:[{alarmCode: "XJBJ202310300067",lat: "39.914083",log: "116.265872",icon: ""}] // 必须含有坐标点数据icon // 加工标记点数据 const pointArr = arr.map((item: any) => ([Number(item.lng), Number(item.lat)])) console.log(pointArr, 'pointArr') // if (pointArr.length) { // map.value.setCenter(pointArr[0]) // } map.value.setFitView() const AMap = AMapRef.value // 标记点绘制 for (let i = 0; i < arr.length; i++) { // 自定义icon const icon = new AMap.Icon({ size: new AMap.Size(36, 36), // 图标尺寸 image: arr[i].icon, // Icon的图像 imageSize: new AMap.Size(24, 30), // 根据所设置的大小拉伸或压缩图片 imageOffset: new AMap.Pixel(0, 0), // 图像相对展示区域的偏移量,适于雪碧图等 }) // 标记点 const marker = new AMap.Marker({ // zooms: [16, 20], // 缩放 position: pointArr[i], // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9] map: map.value, icon, offset: new AMap.Pixel(3, -30), }) markerList.value.push(marker) // 信息窗体 infoWindow.value = new AMap.InfoWindow({ isCustom: true, // 自定义信息窗体 content: windowInfoRef.value.$el, // 窗体内容(vue组件) offset: new AMap.Pixel(9, -5), // 偏移 }) // 信息窗体点击事件 marker.on('click', (e) => { // 打开信息窗口 infoWindow.value.open(map.value, e.lnglat) // 初始化信息窗口 windowInfoRef.value.initialize({ overlay: e.target, infoWindow: infoWindow.value, // 标记点详细信息 info: arr[i], }) }) // 将标记点添加到地图 map.value.add([marker]) } } // 绘制折线(轨迹) const drawLine = (arr: any[]) => { // 先绘制点 // 加工标记点数据 const pointArr = arr.map((item: any) => ([Number(item.lng), Number(item.lat)])) const AMap = AMapRef.value // 标记点绘制 for (let i = 0; i < arr.length; i++) { // 自定义标记点 const markerContent = '' + '<div class="content-marker">' + `${i + 1}` + '</div>' // 标记点 const marker = new AMap.Marker({ // zooms: [16, 20], // 缩放 position: pointArr[i], // 经纬度对象,也可以是经纬度构成的一维数组[116.39, 39.9] map: map.value, content: markerContent, offset: new AMap.Pixel(0, 0), }) lineMarkerList.value.push(marker) // 信息窗体 infoWindow.value = new AMap.InfoWindow({ isCustom: true, // 自定义信息窗体 content: windowInfoRef.value.$el, // 窗体内容(vue组件) offset: new AMap.Pixel(9, -5), // 偏移 }) // 信息窗体点击事件 marker.on('click', (e) => { // 打开信息窗口 infoWindow.value.open(map.value, e.lnglat) // 初始化信息窗口 windowInfoRef.value.initialize({ overlay: e.target, infoWindow: infoWindow.value, // 标记点详细信息 info: arr[i], }) }) // 将标记点添加到地图 map.value.add([marker]) } // 折线绘制 const polyline = new AMap.Polyline({ path: pointArr, // isOutline: true, strokeColor: '#ff0', strokeOpacity: 1, strokeWeight: 4, // 折线样式还支持 'dashed' // strokeStyle: 'dashed', // strokeStyle是dashed时有效 strokeDasharray: [10, 3], lineJoin: 'round', showDir: true, // lineCap: 'square', lineCap: 'round', zIndex: 50, // zooms: [16, 20], }) lineList.value = polyline polyline.setMap(map.value) map.value.add(polyline) map.value.setFitView() } // 清空所有绘制 const clearDraw = () => { map.value.setFitView() map.value.clearMap() } // 清空标记点 const clearPonit = () => { map.value.setFitView() if (markerList.value.length) { map.value.remove(markerList.value) markerList.value = [] } } // 清空折线(轨迹) const clearLine = () => { map.value.setFitView() // 先清空折线的标记点 if (lineMarkerList.value.length) { map.value.remove(lineMarkerList.value) lineMarkerList.value = [] } // 再清空折线 if (lineList.value) { map.value.remove(lineList.value) lineList.value = '' } } defineExpose({ drawPonit, clearDraw, isMap, drawLine, clearPonit, clearLine }) </script> <template> <div id="container" style="width: 100%; height: 100%;" /> <!-- <div class="input-item"> <input id="toolbar" type="checkbox" onclick="toggleToolBar(this)">工具条 </div> --> <!-- 信息窗体 --> <info-dialog ref="windowInfoRef" /> </template> <style lang="scss" scope> .content-marker { border-radius: 50%; width: 16px; height: 16px; background-color: rgba(#ff0, 0.8); border: 1px solid #ccc; line-height: 16px; text-align: center; font-size: 18px; font-weight: 700; } </style>