<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="initial-scale=1.0, user-scalable=no, width=device-width"> <title>判断塔吊(范围)是否超出限定区域</title> <link rel="stylesheet" href="https://ss.netnr.com/bootstrap@5.3.3/dist/css/bootstrap.min.css" /> <script src="https://webapi.amap.com/maps?v=1.4.15&key=309f07ac6bc48160e80b480ae511e1e9&plugin=AMap.PolyEditor,AMap.CircleEditor"> </script> </head> <body> <div class="container-fluid"> <div class="row"> <div class="col-lg-8"> <div id="container" style="height: 80vh;"></div> </div> <div class="col-lg-4"> <h4 class="mt-3">判断塔吊(范围)是否超出限定区域</h4> <div class="mb-3"> <input type="text" class="form-control-plaintext" value="地图初始化坐标: 116.40139,39.90061" readonly> </div> <div class="input-group mb-3"> <span class="input-group-text">区域坐标</span> <textarea class="form-control txt-path-area" rows="7"> 116.399653, 39.900874 116.401992, 39.901722 116.4033, 39.900255 116.402099, 39.898988 116.400188, 39.899349 </textarea> </div> <div class="mb-3"> <button class="btn btn-primary btn-view-area">显示区域</button> <button class="btn btn-primary btn-remove-area">删除区域</button> <button class="btn btn-outline-primary btn-start-edit-area">开始编辑区域</button> <button class="btn btn-outline-primary btn-end-edit-area">结束编辑区域</button> </div> <hr /> <div class="input-group mb-3"> <span class="input-group-text">塔吊坐标</span> <input class="form-control txt-path-device" value="116.40139,39.900379"> </div> <div class="input-group mb-3"> <span class="input-group-text">塔吊半径</span> <input class="form-control txt-radius-device" value="50"> <span class="input-group-text">米</span> </div> <div class="mb-3"> <button class="btn btn-info btn-view-device">显示塔吊</button> <button class="btn btn-info btn-remove-device">删除塔吊</button> <button class="btn btn-outline-info btn-start-edit-device">开始编辑塔吊</button> <button class="btn btn-outline-info btn-end-edit-device">结束编辑塔吊</button> </div> <hr /> <div class="mb-3"> <button class="btn btn-warning btn-inarea1">判断塔吊(中心)是否超出限定区域</button> <span class="result1 badge text-bg-danger"></span> </div> <div class="mb-3"> <button class="btn btn-warning btn-inarea2">判断塔吊(范围)是否超出限定区域</button> <span class="result2 badge text-bg-danger"></span> </div> </div> </div> </div> </body> </html>
let nrMap = { init: () => { nrMap.map = new AMap.Map("container", { center: [116.40139, 39.90061], zoom: 14 }); nrMap.bindEvent(); }, map: null, // 地图对象 polygon: null, // 多边形对象 polygonEditor: null, // 多边形编辑器 bindEvent: () => { // 监听地图的右键点击事件 nrMap.map.on('rightclick', function (e) { var lng = e.lnglat.getLng(); // 获取经度 var lat = e.lnglat.getLat(); // 获取纬度 let path = `${lng},${lat}`; if (confirm(`${lng},${lat}`)) { navigator.clipboard.writeText(path); } }); // 显示区域 document.querySelector('.btn-view-area').addEventListener('click', () => { let pathArea = document.querySelector('.txt-path-area').value.split('\n') .filter(x => x.includes(",")) .map(x => x.split(',').map(x => parseFloat(x))); nrMap.drawArea(pathArea); }); // 删除区域 document.querySelector('.btn-remove-area').addEventListener('click', () => { if (nrMap.polygonEditor) { nrMap.polygonEditor.close(); nrMap.map.remove(nrMap.polygon); } }); // 开始编辑区域 document.querySelector('.btn-start-edit-area').addEventListener('click', () => { nrMap.polygonEditor.open(); }); // 结束编辑区域 document.querySelector('.btn-end-edit-area').addEventListener('click', () => { nrMap.polygonEditor.close(); // 获取多边形的顶点 let path = nrMap.polygon.getPath().map(x => `${x.lng},${x.lat}`).join('\n'); document.querySelector('.txt-path-area').value = path; }); // 显示塔吊 document.querySelector('.btn-view-device').addEventListener('click', () => { let center = document.querySelector('.txt-path-device').value.split(',').map(x => parseFloat(x)); let radius = parseFloat(document.querySelector('.txt-radius-device').value); nrMap.drawCircle(center, radius); }); // 删除塔吊 document.querySelector('.btn-remove-device').addEventListener('click', () => { if (nrMap.circle) { nrMap.map.remove(nrMap.circle); nrMap.circle = null; nrMap.marker.setMap(null); nrMap.marker = null; } }); // 开始编辑塔吊 document.querySelector('.btn-start-edit-device').addEventListener('click', () => { // 编辑塔吊后不能拖拽 nrMap.circleEditor = new AMap.CircleEditor(nrMap.map, nrMap.circle); nrMap.circleEditor.open(); }); // 结束编辑塔吊 document.querySelector('.btn-end-edit-device').addEventListener('click', () => { nrMap.circleEditor.close(); let center = nrMap.circle.getCenter(); // 更新塔吊中心标点 nrMap.newMarker(center); document.querySelector('.txt-radius-device').value = nrMap.circle.getRadius(); document.querySelector('.txt-path-device').value = `${center.lng}, ${center.lat}`; }); // 判断塔吊中心是否超出区域 document.querySelector('.btn-inarea1').addEventListener('click', () => { let pathArea = document.querySelector('.txt-path-area').value.split('\n') .filter(x => x.includes(",")) .map(x => x.split(',').map(x => parseFloat(x))); let center = document.querySelector('.txt-path-device').value.split(',').map(x => parseFloat(x)); let radius = parseFloat(document.querySelector('.txt-radius-device').value); let isInArea = AMap.GeometryUtil.isPointInRing(center, pathArea); let domResult = document.querySelector('.result1'); domResult.classList.remove('text-bg-danger'); domResult.classList.remove('text-bg-success'); domResult.classList.add(isInArea ? 'text-bg-success' : 'text-bg-danger'); domResult.innerText = isInArea ? '在限定区域内' : '不在限定区域内'; }); // 判断塔吊范围是否超出区域 document.querySelector('.btn-inarea2').addEventListener('click', () => { let domResult = document.querySelector('.result2'); domResult.classList.remove('text-bg-danger'); domResult.classList.remove('text-bg-success'); if (nrMap.polygon == null || nrMap.circle == null) { domResult.classList.add('text-bg-danger'); domResult.innerText = '请先点显示区域和塔吊'; return; } let pathArea = document.querySelector('.txt-path-area').value.split('\n') .filter(x => x.includes(",")) .map(x => x.split(',').map(x => parseFloat(x))); let center = document.querySelector('.txt-path-device').value.split(',').map(x => parseFloat(x)); let radius = parseFloat(document.querySelector('.txt-radius-device').value); let isInArea = AMap.GeometryUtil.isPointInRing(center, pathArea); if (isInArea) { let point = new AMap.LngLat(center[0], center[1]); // 要计算距离的点 let min = nrMap.getPointToPolygonMinLength(point, nrMap.polygon); if (min >= radius) { domResult.classList.add('text-bg-success'); domResult.innerText = '在限定区域内'; } else { domResult.classList.add('text-bg-danger'); domResult.innerText = '不在限定区域内'; } } else { domResult.classList.add('text-bg-danger'); domResult.innerText = '不在限定区域内'; } }); }, // 画区域 drawArea: (path) => { if (nrMap.polygon) { nrMap.polygonEditor.close(); nrMap.map.remove(nrMap.polygon); } nrMap.polygon = new AMap.Polygon({ path: path, strokeColor: "#0f5132", strokeWeight: 6, strokeOpacity: 0.2, fillOpacity: 0.2, fillColor: '#198754', zIndex: 50, draggable: true }) nrMap.map.add(nrMap.polygon) // 缩放地图到合适的视野级别 nrMap.map.setFitView([nrMap.polygon]) // 拖动区域 nrMap.polygon.on('dragend', () => { let path = nrMap.polygon.getPath(); // 获取多边形的顶点 let pathStr = path.map(x => `${x.lng}, ${x.lat}`).join('\n'); document.querySelector('.txt-path-area').value = pathStr; }) // 编辑多边形 nrMap.polygonEditor = new AMap.PolyEditor(nrMap.map, nrMap.polygon) }, // 画圆 drawCircle: (center, radius) => { if (nrMap.circle) { nrMap.map.remove(nrMap.circle); } // 更新塔吊中心标点 nrMap.newMarker(center); nrMap.circle = new AMap.Circle({ center: center, radius: radius, strokeColor: "#FF33FF", strokeWeight: 6, strokeOpacity: 0.2, fillOpacity: 0.6, fillColor: '#0dcaf0', zIndex: 50, draggable: true }) nrMap.map.add(nrMap.circle) // 缩放地图到合适的视野级别 if (nrMap.polygon == null) { nrMap.map.setFitView([nrMap.circle]); } // 拖动圆形 nrMap.circle.on('dragend', () => { let center = nrMap.circle.getCenter(); // 更新塔吊中心标点 nrMap.newMarker(center); document.querySelector('.txt-path-device').value = `${center.lng}, ${center.lat}`; }) }, // 点到多边形的最短距离 getPointToPolygonMinLength: (point, polygon) => { // 获取多边形的路径(顶点坐标) var path = polygon.getPath(); // 计算点到多边形每条边的距离,并找到最小值 var minDistance = Infinity; for (var i = 0; i < path.length; i++) { var start = path[i]; var end = path[(i + 1) % path.length]; var distance = AMap.GeometryUtil.distanceToSegment(point, start, end); minDistance = Math.min(minDistance, distance); } return minDistance; }, newMarker: (center) => { if (nrMap.marker) { nrMap.marker.setMap(null); nrMap.marker = null; } nrMap.marker = new AMap.Marker({ position: center, label: { offset: new AMap.Pixel(16, 18), //修改label相对于marker的位置 content: "塔吊", } }); nrMap.marker.setMap(nrMap.map); } } nrMap.init();