From 4fe156325eea6737e56a5090a9a905eaaa6163b1 Mon Sep 17 00:00:00 2001 From: wangchengming <15110151257@163.com> Date: Fri, 12 Sep 2025 15:20:28 +0800 Subject: [PATCH] =?UTF-8?q?=E6=8F=90=E4=BA=A4=E5=AA=92=E4=BD=93=E5=9C=B0?= =?UTF-8?q?=E5=9B=BE=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/views/mediaMap/index.vue | 285 ++++++++++++++++++++++++++++++++--- 1 file changed, 263 insertions(+), 22 deletions(-) diff --git a/src/views/mediaMap/index.vue b/src/views/mediaMap/index.vue index 5d00c85..9e57aa0 100644 --- a/src/views/mediaMap/index.vue +++ b/src/views/mediaMap/index.vue @@ -5,8 +5,20 @@ - + + + +
{{ item.name }}
+
{{ + item.address + }}
+
+
@@ -41,13 +53,31 @@ import { useBackgroundStore } from '@/store/modules/background' import otherbg from '@/assets/images/otherbg.png' import { mediaByMap } from "@/api/mediaLibrary" -import { rAF } from 'element-plus/es/utils/raf.mjs'; const bgStore = useBackgroundStore() const { proxy } = getCurrentInstance() const { apiKey, secretKey } = window._CONFIG +// map实例 +const mapInstance = ref(null) +const massMarks = ref(null) +const centerMarker = ref(null) +// 当前地图模式(2D/3D) +const mapMode = ref('2D') +// 是否全屏状态 +const isFullscreen = ref(false) +const placeSearch = ref(null) + +// 热区圆实例 +const circle = ref(null); +const circleRadius = ref(2000); // 实际半径(米) +const circleHandle = ref(null); // 拖拽手柄 + +// 选择地点展示框 +const selectLoading = ref(false) +const localeList = ref([]) + // 距离显示文本 const distanceLable = ref('请选择') // 选择的距离值 @@ -79,23 +109,211 @@ const resetQuery = () => { y: undefined, //中心点纬度 distance: undefined, } - handleQuery() + // 距离显示文本 + distanceLable.value = '请选择' + // 选择的距离值 + activeLableIndex.value = null + circleRadius.value = 2000; // 实际半径(米) + + // 清除现有的圆形和标记 + if (centerMarker.value) { + mapInstance.value.remove(centerMarker.value); + centerMarker.value = null; + } + if (circle.value) { + mapInstance.value.remove(circle.value); + circle.value = null; + } + if (circleHandle.value) { + mapInstance.value.remove(circleHandle.value); + circleHandle.value = null; + } + + // 重新渲染数据点 + renderMassMarks() } + +// 调用API获取地点 +const getLocaleListList = (searchValue) => { + selectLoading.value = true + if (searchValue !== "") { + placeSearch.value.search(searchValue, function (status, result) { + // 查询成功时,result即对应匹配的POI信息 + console.log(result.poiList, result.poiList.pois, result.poiList.pois?.length) + if (result.poiList.pois?.length) { + localeList.value = result.poiList?.pois + } + selectLoading.value = false + }); + } +} +// 中心点选择 +const currentSelect = (val) => { + console.log('val', val) + queryParams.value.keyword = val.name + queryParams.value.x = val.location.lng + queryParams.value.y = val.location.lat + queryParams.value.distance = circleRadius.value + + // 距离显示文本 + distanceLable.value = '2000米' + // 选择的距离值 + activeLableIndex.value = 2000 + + // 清除现有的圆形和标记 + if (circle.value) { + mapInstance.value.remove(circle.value); + circle.value = null; + } + if (circleHandle.value) { + mapInstance.value.remove(circleHandle.value); + circleHandle.value = null; + } + + createCircle(val) + addCenterMark(val) +} +// 创建中心点标记 +const addCenterMark = (val) => { + if (centerMarker.value) mapInstance.value.remove(centerMarker.value); + centerMarker.value = new AMap.Marker({ + position: [val.location.lng, val.location.lat], + title: val.name, + zIndex: 100, + draggable: false, // 是否可以拖拽 + cursor: 'move' + }); + // 将点添加到地图 + mapInstance.value.add(centerMarker.value); + mapInstance.value.setFitView(); +} + +// 创建圆形热区 +const createCircle = (val) => { + // 创建圆形覆盖物 + circle.value = new AMap.Circle({ + center: [val.location.lng, val.location.lat], + radius: circleRadius.value, + strokeColor: '#4e54c8', + strokeOpacity: 0.8, + strokeWeight: 2, + fillColor: '#4e54c8', + fillOpacity: 0.15, + zIndex: 100, + bubble: true, + cursor: 'move', + draggable: false // 是否可以拖拽 + }); + + // 将圆形添加到地图 + mapInstance.value.add(circle.value); + + // 创建圆形边缘拖拽手柄 + createCircleHandle(); + + // 渲染数据点 + renderMassMarks() +} + + +// 创建圆形边缘拖拽手柄 +const createCircleHandle = () => { + // 计算手柄的初始位置(圆形右侧边缘) + const center = circle.value.getCenter(); + const radius = circle.value.getRadius(); + // 更精确地计算手柄位置 + const handlePosition = new AMap.LngLat( + center.lng + radius / (111320 * Math.cos(center.lat * Math.PI / 180)), + center.lat + ); + console.log('手柄', handlePosition) + // 创建手柄标记 + circleHandle.value = new AMap.Marker({ + position: [handlePosition.lng, handlePosition.lat], + icon: new AMap.Icon({ + size: new AMap.Size(20, 20), + image: '//a.amap.com/jsapi_demos/static/demo-center/icons/poi-marker-default.png', + imageSize: new AMap.Size(20, 20) + }), + offset: new AMap.Pixel(-10, -10), + zIndex: 101, + draggable: true, + cursor: 'pointer' + }); + + mapInstance.value.add(circleHandle.value); + + // 监听手柄拖拽事件 + circleHandle.value.on('dragging', (e) => { + const handlePos = e.lnglat; + const center = circle.value.getCenter(); + const newRadius = Math.round(calculateDistance(center, handlePos)); + circleRadius.value = newRadius; + distanceLable.value = `${Math.round(circleRadius.value)}米`; + queryParams.value.distance = circleRadius.value // 更改查询条件距离 + if (circleRadius.value !== 1000 && circleRadius.value !== 2000 && circleRadius.value !== 3000 && circleRadius.value !== 5000) activeLableIndex.value = null + else activeLableIndex.value = circleRadius.value + circle.value.setRadius(newRadius); + }); + + circleHandle.value.on('dragend', () => { + // 拖拽结束后更新手柄位置 + updateCircleHandlePosition(); + // 重新渲染数据点 + renderMassMarks() + }); +} +// 更新圆形拖拽手柄位置 +const updateCircleHandlePosition = () => { + if (!circle.value || !circleHandle.value) return; + + const center = circle.value.getCenter(); + const radius = circle.value.getRadius(); + + const handlePosition = new AMap.LngLat( + center.lng + radius / (111320 * Math.cos(center.lat * Math.PI / 180)), + center.lat + ); + + circleHandle.value.setPosition(handlePosition); +}; +// 计算两点之间的距离(米) +const calculateDistance = (point1, point2) => { + const lng1 = point1.lng; + const lat1 = point1.lat; + const lng2 = point2.lng; + const lat2 = point2.lat; + + const radLat1 = lat1 * Math.PI / 180.0; + const radLat2 = lat2 * Math.PI / 180.0; + const a = radLat1 - radLat2; + const b = lng1 * Math.PI / 180.0 - lng2 * Math.PI / 180.0; + + let distance = 2 * Math.asin(Math.sqrt(Math.pow(Math.sin(a / 2), 2) + + Math.cos(radLat1) * Math.cos(radLat2) * Math.pow(Math.sin(b / 2), 2))); + distance = distance * 6378.137; + distance = Math.round(distance * 10000) / 10; + + return distance; +}; + // 选择距离 const handleChangeDistance = (itemDistance) => { queryParams.value.distance = itemDistance.value activeLableIndex.value = itemDistance.value - distanceLable.value = itemDistance.label + distanceLable.value = itemDistance.value + '米' + + // 更新热区 + circleRadius.value = itemDistance.value; + circle.value.setRadius(itemDistance.value); + updateCircleHandlePosition(); + + // 重新渲染数据点 + renderMassMarks() } -// map实例 -const mapInstance = ref(null) -const massMarks = ref(null) -// 当前地图模式(2D/3D) -const mapMode = ref('2D') -// 是否全屏状态 -const isFullscreen = ref(false) + // 初始化地图 const loadMap = () => { return new Promise((resolve, reject) => { @@ -106,7 +324,7 @@ const loadMap = () => { AMapLoader.load({ key: apiKey, - plugins: [], + plugins: ["AMap.PlaceSearch"], AMapUI: { plugins: [] } @@ -117,18 +335,23 @@ const loadMap = () => { mapInstance.value = new AMap.Map("mapContainer", { resizeEnable: true, - zoom: 14, - center: [116.397428, 39.90923], // 默认中心点 + // center: [116.397428, 39.90923], // 默认中心点 pitch: initialPitch, // 倾斜角度决定2D/3D模式 rotation: initialRotation, // 旋转角度 - buildingAnimation: true, - expandZoomRange: true, - zooms: [3, 20], + // buildingAnimation: true, + // expandZoomRange: true, + zoom: 16, + zooms: [3, 16], viewMode: mapMode.value // 启用3D视图 }); - // 先添加基本控件 - mapInstance.value.setZoom(14); + // // 先添加基本控件 + mapInstance.value.setZoom(16); + + placeSearch.value = new AMap.PlaceSearch({ + // city 指定搜索所在城市,支持传入格式有:城市名、citycode和adcode + city: '全国' + }) // 添加自定义控件容器 addCustomControls(AMap); @@ -141,6 +364,8 @@ const loadMap = () => { // 监听地图渲染完成事件 mapInstance.value.on('render', hideAmapLogo); + // 添加缩放变化监听 + mapInstance.value.on('zoomchange', handleZoomChange); // 在地图完全加载后执行点数据处理 renderMassMarks(); @@ -152,6 +377,15 @@ const loadMap = () => { }); }); } +// 处理地图缩放事件 +const handleZoomChange = () => { + const currentZoomLevel = mapInstance.value.getZoom(); + // 如果缩放级别超过16,自动调整回16 + if (currentZoomLevel > 16) { + mapInstance.value.setZoom(16); + return; + } +} // 添加自定义控件 const addCustomControls = (AMap) => { // 创建控件容器 @@ -312,7 +546,7 @@ const renderMassMarks = () => { if (itemPoint.businessType == 2) points.value.push({ "lnglat": [itemPoint.x, itemPoint.y], "name": itemPoint.mediaId, "style": 1 }) }); } - }).then(res => { + }).then(res => { console.log('points', points.value) // 创建MassMarks对象 massMarks.value = new AMap.MassMarks(points.value, { @@ -342,7 +576,9 @@ const hideAmapLogo = () => { } onUnmounted(() => { - mapInstance.value?.destroy() + if (mapInstance.value) { + mapInstance.value.destroy(); + } }) // 初始化 onMounted(() => { @@ -524,4 +760,9 @@ onMounted(() => { width: 100% !important; height: 100% !important; } + +.one-text { + height: 50px; + padding-top: 4px; +} \ No newline at end of file