<!-- Description: 高德地图 Author: 李亚光 Date: 2023-04-21 --> <script lang="ts" setup name="GuadMap"> import AMapLoader from '@amap/amap-jsapi-loader' // import { styleType } from 'element-plus/es/components/table-v2/src/common' const $props = defineProps({ // 初始图层 normal satellite dark layer: { type: String, default: 'normal', }, center: { type: Array, default: () => ([116.397428, 39.90923]), }, zoom: { type: Number, default: 9, }, }) const $emits = defineEmits(['complete', 'marke', 'mapClick', 'markerClick', 'lineClick', 'polygonClick', 'massMarksClick']) const loading = ref(true) const publicPath = window.location.href.split('#')[0] // 设置安全密钥 window._AMapSecurityConfig = { securityJsCode: localStorage.getItem('securityJsCode')!, // 后期需替换 } // 地图实例 const map = shallowRef() const AMap = ref() // 使用高德地图API的逆地理编码服务 const getPosition = (location: string[], resultFun: Function) => { let position = '' AMap.value.plugin('AMap.Geocoder', () => { var geocoder = new AMap.value.Geocoder() var lnglat = location geocoder.getAddress(lnglat, (status: any, result: any) => { if (status === 'complete' && result.info === 'OK') { // result为对应的地理位置详细信息 console.log(result.regeocode.formattedAddress) position = result.regeocode.formattedAddress resultFun(position) } else { position = '' resultFun(position) } }) }) } // 地图缩放等级 const zoom = ref(0) // 图层 const layer = ref() // 图层标识 const layerFlag = ref('normal') // const publicPath = import.meta.env.BASE_URL // console.log(publicPath, 'publicPath') // -------------------------------------初始化地图-------------------------------------------------- const wrapRef = ref() const initMap = () => { // const offline = window.AMap // const garUrl = new offline.TileLayer({ // // getTileUrl: (a: any, b: any, c: any) => { // // // 经纬度转换成本地瓦片所在路径 // // const flag = '00000000' // // const zz = c // // const z = `L${zz}` // // const xx = a.toString(16) // // const x = `C${flag.substring(0, 8 - xx.length)}${xx}` // // const yy = b.toString(16) // // const y = `R${flag.substring(0, 8 - yy.length)}${yy}` // // // console.log(`${publicPath}allayers/${z}/${y}/${x}.png`) // // return `http://111.198.10.15:21904/amap/${z}/${y}/${x}.png` // // // return 'file:///D:/GisMap/_alllayers/L01/R00000000/C00000001.png' // // }, // getTileUrl(x, y, z) { // return `http://111.198.10.15:21904/amap/${z}/${y}/${x}.png` // }, // opacity: 1, // zIndex: 99, // }) // AMap.value = offline // map.value = new offline.Map('map', { // 设置地图容器id // resizeEnable: true, // viewMode: '3D', // 是否为3D地图模式 // zoom: 10, // 初始化地图级别 // center: $props.center, // 初始化地图中心点位置 // zooms: [8, 14], // layers: [ // new offline.TileLayer({ // visible: true, // zIndex: 1, // opacity: 1, // getTileUrl: (a: any, b: any, c: any) => { // // 经纬度转换成本地瓦片所在路径 // const flag = '00000000' // const zz = c // const z = `L${zz}` // const xx = a.toString(16) // const x = `C${flag.substring(0, 8 - xx.length)}${xx}` // const yy = b.toString(16) // const y = `R${flag.substring(0, 8 - yy.length)}${yy}` // // return `${publicPath}amap/${z}/${y}/${x}.png` // return `http://111.198.10.15:21910/amap/${z}/${y}/${x}.png` // }, // }), // ], // }) // setTimeout(() => { // $emits('complete', AMap.value) // loading.value = false // }, 1500) // map.value.setZoom($props.zoom) AMapLoader.load({ key: localStorage.getItem('JsKey')!, // 后期需替换 version: '2.0', // 指定要加载的 JSAPI 的版本,缺省时默认为 1.4.15 plugins: ['AMap.Scale', 'AMap.MouseTool', 'AMap.Geocoder'], // 需要使用的的插件列表,如比例尺'AMap.Scale'等 }) .then((AMap1: any) => { AMap.value = AMap1 // 初始化地图 map.value = new AMap1.Map('map', { viewMode: '3D', // 是否为3D地图模式 zoom: $props.zoom, // 初始化地图级别 resizeEnable: true, center: $props.center, }) // 图层 if ($props.layer === 'satellite') { // 卫星图层 layer.value = new AMap.value.TileLayer.Satellite() map.value.addLayer(layer.value) map.value.setFeatures(['bg', 'building']) layerFlag.value = 'satellite' } else if ($props.layer === 'dark') { // 深色图层 map.value.setMapStyle('amap://styles/darkblue') // map.value.setMapStyle('http://111.198.10.15:21904/amap/skyblue?isPublic=true') } // // 地图图块加载完成后触发 map.value.on('complete', () => { // 修改loading状态 console.log('地图加载完成') setTimeout(() => { $emits('complete', AMap.value) loading.value = false }, 1500) // AMap.value.reGeocode({ // location: $props.center, // success: (res: any) => { // // 获取到详细地址信息 // const formattedAddress = res.regeocode.formattedAddress // console.log('地址:', formattedAddress) // }, // error: (err: any) => { // console.error('获取地址失败:', err) // }, // }) }) // 地图绑定右击事件 map.value.on('mousedown', clickHandler) // 地图绑定点击击事件 map.value.on('click', (e: any) => { $emits('mapClick', e) }) // // 地图zoom map.value.on('zoomend', () => { zoom.value = map.value.getZoom() // 获取当前缩放级别 console.log('当前缩放级别:', zoom.value) }) }) .catch((e) => { console.log(e, '地图加载失败') }) } // ------------------------------------------------------------------------------------------------ function clickHandler(e) { const location = [e.lnglat.getLng(), e.lnglat.getLat()] if (event.button === 2) { console.log('当前点击坐标为: ', location) } } // -------------------------------------切换图层---------------------------------------------------- const changeLayerGrop = () => { if (layerFlag.value === 'normal') { layer.value = new AMap.value.TileLayer.Satellite() map.value.addLayer(layer.value) map.value.setFeatures(['bg', 'building']) layerFlag.value = 'satellite' } else { map.value.removeLayer(layer.value) layerFlag.value = 'normal' } } // ------------------------------------------------------------------------------------------------ // -------------------------------------多边形操作-------------------------------------------------- // 多边形数组 const polygonAllList = ref<any>([]) // 绘制多边形 function addPolygon(data: any[], style = { name: '', fillColor: '#ccebc5', // //多边形填充颜色 strokeOpacity: 1, // 多边形填充透明度 fillOpacity: 0.3, // 多边形填充透明度 strokeColor: '#2b8cbe', // 线条颜色 strokeWeight: 2, // 轮廓线宽度 strokeStyle: 'dashed', strokeDasharray: [5, 5], activeFillColor: '#7bccc4', // 鼠标进入多边形的激活颜色 dbclickSetCenter: false, // 双击多边形自动放大切切换中心试图 dbclickCenter: [], // 中心坐标 needHover: true, }) { const polygon = new AMap.value.Polygon({ path: data, // 边界数据 fillColor: style.fillColor, strokeOpacity: style.strokeOpacity, fillOpacity: style.fillOpacity, strokeColor: style.strokeColor, strokeWeight: style.strokeWeight, strokeStyle: style.strokeStyle, strokeDasharray: style.strokeDasharray, }) polygon.on('mouseover', () => { if (!style.needHover) { return } polygon.setOptions({ fillOpacity: style.fillOpacity + 0.2, fillColor: style.activeFillColor, }) }) polygon.on('mouseout', () => { if (!style.needHover) { return } polygon.setOptions({ fillOpacity: style.fillOpacity, fillColor: style.fillColor, }) }) polygon.on('mousedown', clickHandler) // if (style.dbclickSetCenter) { polygon.on('dblclick', (e) => { console.log(`当前点击的是${style.name}`) $emits('polygonClick', { event: e, map: map.value, style }) }) polygonAllList.value.push(polygon) // } map.value.add(polygon) } // 移除多边形 const removePolygon = () => { polygonAllList.value.forEach((item: any) => { item.setMap(null) }) polygonAllList.value = [] console.log('清除绘制的多边形') } // ------------------------------------------------------------------------------------------------ // -------------------------------------标记文本操作-------------------------------------------------- // 标记文本数组 const textAllList = ref<any>([]) // 添加标记文字 function addText(data: any, style = { /** * data 示例 * text: 文本内容 * position: 位置 */ // 'padding': '.75rem 1.25rem', // 'width': '15rem', // 'border-width': 0, // 'text-align': 'center', 'font-size': '18px', 'color': 'white', 'background-color': 'transparent', 'border-color': 'transparent', }) { // 创建纯文本标记 var Text = new AMap.value.Text({ text: data.text, // 文本内容 anchor: 'center', // 设置文本标记锚点 draggable: false, // 是否可拖拽 cursor: '', // 鼠标样式 angle: 0, // 旋转角度 style, // 文本样式 position: data.position, // 点标记在地图上显示的位置 }) textAllList.value.push(Text) Text.setMap(map.value) } // 移除标记文字 const removeText = () => { textAllList.value.forEach((item: any) => { item.setMap(null) }) textAllList.value = [] } // ------------------------------------------------------------------------------------------------ // -------------------------------------点标记操作-------------------------------------------------- // 点标记(一般点标记)数组 const markerAllList = ref<any>([]) const markerHtml = `<img width="19px" height="32px" src="${publicPath}/image/mark_bs.png" />` // 添加点标记 (一般点标记) const addMarker = (data: any) => { /** * data 示例 * position: 位置 * content: 标记点内容 html * label: 文本标记 */ var marker = new AMap.value.Marker({ position: data.position, // 将 html 传给 content content: data.content || markerHtml, // 以 icon 的 [center bottom] 为原点 offset: new AMap.value.Pixel(0, 0), }) markerAllList.value.push(marker) // markers的信息窗体 marker.on('click', (e: any) => { console.log('标记点') $emits('markerClick', { event: e, map: map.value, data, marker }) }) // 标记点文本标记 marker.setLabel({ offset: new AMap.value.Pixel(0, -5), // 设置文本标注偏移量 content: `<div style="color:white;font-size:15px;">${data.label}</div>`, // 设置文本标注内容 direction: 'top-center', // 设置文本标注方位 }) // 将 markers 添加到地图 map.value.add(marker) } // 移除点标记 (一般点标记) const removeMarker = () => { markerAllList.value.forEach((item: any) => { item.setMap(null) }) markerAllList.value = [] } // ------------------------------------------------------------------------------------------------ // -------------------------------------绘线操作-------------------------------------------------- // 折线数组 const lineAllList = ref<any[]>([]) // 添加折线 const addPolyline = (data: any) => { /** * data : {path: [],style: {}} * path: 折线点位数据 [[],[],[]] * style 折线样式 * style样式参考 * isOutline: true, outlineColor: '#ffeeff', borderWeight: 3, strokeColor: "#3366FF", strokeOpacity: 1, strokeWeight: 6, // 折线样式还支持 'dashed' strokeStyle: "dashed", // strokeStyle是dashed时有效 strokeDasharray: [15, 5], lineJoin: 'round', lineCap: 'round', zIndex: 50, */ var polyline = new AMap.value.Polyline({ path: data.path.map((item: any) => (new AMap.value.LngLat(Number(item[0]), Number(item[1])))), ...data.style, }) polyline.on('click', (e) => { console.log('点击了线') $emits('lineClick', { event: e, map: map.value, data, polyline }) }) console.log(polyline, 'polyline') lineAllList.value.push(polyline) map.value.add([polyline]) } // 移除折线 const removePolyline = () => { lineAllList.value.forEach((item: any) => { item.setMap(null) }) lineAllList.value = [] } // ------------------------------------------------------------------------------------------------ // -----------------------------------海量点标记操作------------------------------------------------ // 点标记(海量点)数组 const massMarksAllList = ref<any>([]) // 添加点标记(海量点) const addMassMarks = (data: any) => { var massMarks = new AMap.value.MassMarks(data.path, { zIndex: data.zIndex, // 海量点图层叠加的顺序 zooms: data.zooms || [], // 在指定地图缩放级别范围内展示海量点图层 style: data.style, // 设置样式对象 }) massMarksAllList.value.push(massMarks) massMarks.setMap(map.value) massMarks.on('click', (e) => { console.log('点击了海量点标记') $emits('massMarksClick', { event: e, map: map.value, data, massMarks }) }) } // 移除点标记(海量点) const removeMassMarks = () => { massMarksAllList.value.forEach((item: any) => { item.setMap(null) }) massMarksAllList.value = [] } // ------------------------------------------------------------------------------------------------ // -------------------------------------绘线操作---------------------------------------------------- const massLineAllList = ref<any>([]) // 海量线数组 // 添加折线(海量) const addMassLine = (data: any) => { /** * data * path: 折线点位数据 [[],[],[]] * style 折线样式 * style样式参考 strokeColor: "#3366FF", strokeWeight: 6, // 折线样式还支持 'dashed' strokeStyle: "solid", zIndex: 50, zoomLevels: [1,18] */ // const multiPolyline = new AMap.value.MultiPolyline({ // map: map.value, // styles: { // ...data.style, // }, // }) // massLineAllList.value.push(multiPolyline) // multiPolyline.setPaths(data.path) } // 移除折线 const removeMassLine = () => { // massLineAllList.value.forEach((item: any) => { // item.setMap(null) // }) // massLineAllList.value = [] } // ------------------------------------------------------------------------------------------------ onMounted(() => { loading.value = true initMap() }) onBeforeUnmount(() => { if (map.value) { map.value.destroy() } }) defineExpose({ map, AMap, zoom, // 当前缩放等级 changeLayerGrop, // 切换图层 layerFlag, // 当前图层标识 polygonAllList, // 多边形区域数据 addPolygon, // 绘制多边形区域 removePolygon, // 移除多边形 addText, // 添加标记文字 removeText, // 移除标记文字 addMarker, // 添加点标记 (一般点标记) removeMarker, // 移除点标记 (一般点标记) addPolyline, // 添加折线 lineAllList, // 折线数组 removePolyline, // 移除折线 addMassMarks, // 添加点标记(海量点) massMarksAllList, removeMassMarks, // 移除点标记(海量点) addMassLine, // 添加折线(海量线) removeMassLine, // 移除折线(海量线) getPosition, // 根据坐标获取详细位置信息 }) </script> <template> <div class="container"> <!-- 地图 --> <div id="map" ref="wrapRef " v-loading="loading" /> </div> </template> <style lang="scss" scoped> .container { height: 100%; width: 100%; } ::v-deep(.amap-marker-label) { background-color: transparent; border: none; } #map { overflow: hidden; width: 100%; height: 100%; margin: 0; font-family: "微软雅黑"; } </style> <style> /* 隐藏高德logo */ .amap-logo { display: none !important; } /* 隐藏高德版权 */ .amap-copyright { display: none !important; } .img-map-marker { width: 20px; height: 20px; } </style>