From a70852fdc9cb1b23d82925ecd2b9987f7c2b99dc Mon Sep 17 00:00:00 2001 From: yarnom Date: Fri, 4 Jul 2025 09:37:25 +0800 Subject: [PATCH] =?UTF-8?q?feat:=20=E6=96=B0=E5=A2=9E=E6=B5=8B=E8=B7=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../templates/page/device_overview.html | 450 ++++++++++++------ 1 file changed, 302 insertions(+), 148 deletions(-) diff --git a/sec-beidou/src/main/resources/templates/page/device_overview.html b/sec-beidou/src/main/resources/templates/page/device_overview.html index 95752d25..c3d8a838 100644 --- a/sec-beidou/src/main/resources/templates/page/device_overview.html +++ b/sec-beidou/src/main/resources/templates/page/device_overview.html @@ -190,6 +190,54 @@ background: rgba(230, 230, 230, 0.6); } + /* 比例尺样式 */ + .map-scale { + position: absolute; + bottom: 20px; + left: 20px; + z-index: 1000; + background: rgba(255, 255, 255, 0.9); + padding: 8px 12px; + border-radius: 6px; + box-shadow: 0 2px 8px rgba(0, 0, 0, 0.1); + font-size: 12px; + color: #333; + font-weight: bold; + border: 1px solid rgba(0, 0, 0, 0.1); + } + + /* 测距工具样式 */ + .measure-tooltip { + position: relative; + background: rgba(0, 0, 0, 0.8); + border-radius: 4px; + color: white; + padding: 4px 8px; + opacity: 0.8; + white-space: nowrap; + font-size: 12px; + } + + .measure-tooltip-measure { + opacity: 1; + font-weight: bold; + } + + .measure-tooltip-static { + background-color: #ffcc33; + color: black; + border: 1px solid white; + } + + .help-tooltip { + background: rgba(0, 0, 0, 0.8); + color: white; + padding: 4px 8px; + border-radius: 4px; + font-size: 12px; + white-space: nowrap; + } + .overview-stats { @@ -450,20 +498,21 @@
- + + + + +
@@ -473,6 +522,8 @@ + +
比例尺 1:1000
@@ -490,7 +541,7 @@ var greenFeatures = []; var orangeFeatures = []; var redFeatures = []; - var marker_state = 3; // 1:all; 2:orange; 3:red + var marker_state = 1; // 1:all; 2:orange; 3:red var allFeatures = []; // 存储所有设备标记,用于搜索功能 var currentSearchedDevice = null; // 当前搜索的设备ID var myLocationFeature = null; // 存储"我的位置"标记 @@ -501,6 +552,16 @@ var showCluster = true; var minZoomForLabels = 4; var maxZoomForClustering = 8; + + // 测距相关变量 + var measureSource; + var measureVector; + var measureTooltipElement; + var measureTooltip; + var helpTooltipElement; + var helpTooltip; + var draw; + var measuring = false; // 天地图 API 密钥(fengyarnom@gmail.com) var TIANDITU_KEY = '0c260b8a094a4e0bc507808812cefdac'; @@ -589,38 +650,12 @@ layers: [ new ol.layer.Tile({ source: new ol.source.XYZ({ - url: 'https://t{0-7}.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY, - tileLoadFunction: function(imageTile, src) { - imageTile.getImage().src = src; - imageTile.getImage().onerror = function() { - // 天地图加载失败时切换到高德地图 - var mapTypeSelect = document.getElementById('mapTypeSelect'); - if(mapTypeSelect.value.startsWith('tianditu_')) { - mapTypeSelect.value = 'amap'; - switchMapType('amap'); - layer.msg('天地图加载失败,已自动切换到高德地图'); - layui.form.render('select'); - } - }; - } + url: 'https://t{0-7}.tianditu.gov.cn/img_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=img&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY }) }), new ol.layer.Tile({ source: new ol.source.XYZ({ - url: 'https://t{0-7}.tianditu.gov.cn/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY, - tileLoadFunction: function(imageTile, src) { - imageTile.getImage().src = src; - imageTile.getImage().onerror = function() { - // 天地图加载失败时切换到高德地图 - var mapTypeSelect = document.getElementById('mapTypeSelect'); - if(mapTypeSelect.value.startsWith('tianditu_')) { - mapTypeSelect.value = 'amap'; - switchMapType('amap'); - layer.msg('天地图加载失败,已自动切换到高德地图'); - layui.form.render('select'); - } - }; - } + url: 'https://t{0-7}.tianditu.gov.cn/cia_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cia&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY }) }) ] @@ -629,38 +664,12 @@ layers: [ new ol.layer.Tile({ source: new ol.source.XYZ({ - url: 'https://t{0-7}.tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY, - tileLoadFunction: function(imageTile, src) { - imageTile.getImage().src = src; - imageTile.getImage().onerror = function() { - // 天地图加载失败时切换到高德地图 - var mapTypeSelect = document.getElementById('mapTypeSelect'); - if(mapTypeSelect.value.startsWith('tianditu_')) { - mapTypeSelect.value = 'amap'; - switchMapType('amap'); - layer.msg('天地图加载失败,已自动切换到高德地图'); - layui.form.render('select'); - } - }; - } + url: 'https://t{0-7}.tianditu.gov.cn/vec_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=vec&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY }) }), new ol.layer.Tile({ source: new ol.source.XYZ({ - url: 'https://t{0-7}.tianditu.gov.cn/cva_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY, - tileLoadFunction: function(imageTile, src) { - imageTile.getImage().src = src; - imageTile.getImage().onerror = function() { - // 天地图加载失败时切换到高德地图 - var mapTypeSelect = document.getElementById('mapTypeSelect'); - if(mapTypeSelect.value.startsWith('tianditu_')) { - mapTypeSelect.value = 'amap'; - switchMapType('amap'); - layer.msg('天地图加载失败,已自动切换到高德地图'); - layui.form.render('select'); - } - }; - } + url: 'https://t{0-7}.tianditu.gov.cn/cva_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cva&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY }) }) ] @@ -669,20 +678,7 @@ layers: [ new ol.layer.Tile({ source: new ol.source.XYZ({ - url: 'https://t{0-7}.tianditu.gov.cn/ter_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY, - tileLoadFunction: function(imageTile, src) { - imageTile.getImage().src = src; - imageTile.getImage().onerror = function() { - // 天地图加载失败时切换到高德地图 - var mapTypeSelect = document.getElementById('mapTypeSelect'); - if(mapTypeSelect.value.startsWith('tianditu_')) { - mapTypeSelect.value = 'amap'; - switchMapType('amap'); - layer.msg('天地图矢量图加载失败,已自动切换到高德矢量图'); - layui.form.render('select'); - } - }; - } + url: 'https://t{0-7}.tianditu.gov.cn/ter_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY }) }) ] @@ -691,38 +687,12 @@ layers: [ new ol.layer.Tile({ source: new ol.source.XYZ({ - url: 'https://t{0-7}.tianditu.gov.cn/ter_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY, - tileLoadFunction: function(imageTile, src) { - imageTile.getImage().src = src; - imageTile.getImage().onerror = function() { - // 天地图加载失败时切换到高德地图 - var mapTypeSelect = document.getElementById('mapTypeSelect'); - if(mapTypeSelect.value.startsWith('tianditu_')) { - mapTypeSelect.value = 'amap'; - switchMapType('amap'); - layer.msg('天地图加载失败,已自动切换到高德地图'); - layui.form.render('select'); - } - }; - } + url: 'https://t{0-7}.tianditu.gov.cn/ter_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=ter&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY }) }), new ol.layer.Tile({ source: new ol.source.XYZ({ - url: 'https://t{0-7}.tianditu.gov.cn/cta_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cta&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY, - tileLoadFunction: function(imageTile, src) { - imageTile.getImage().src = src; - imageTile.getImage().onerror = function() { - // 天地图加载失败时切换到高德地图 - var mapTypeSelect = document.getElementById('mapTypeSelect'); - if(mapTypeSelect.value.startsWith('tianditu_')) { - mapTypeSelect.value = 'amap'; - switchMapType('amap'); - layer.msg('天地图加载失败,已自动切换到高德地图'); - layui.form.render('select'); - } - }; - } + url: 'https://t{0-7}.tianditu.gov.cn/cta_w/wmts?SERVICE=WMTS&REQUEST=GetTile&VERSION=1.0.0&LAYER=cta&STYLE=default&TILEMATRIXSET=w&FORMAT=tiles&TILEMATRIX={z}&TILEROW={y}&TILECOL={x}&tk=' + TIANDITU_KEY }) }) ] @@ -837,6 +807,7 @@ } } vectorLayer.changed(); + updateScale(); // 更新比例尺 }); map.on('click', function(evt) { @@ -874,6 +845,7 @@ addDeviceMarkers(); myLocation(); startLocationUpdates(); + updateScale(); // 初始化比例尺 } function switchMapType(mapType) { @@ -970,6 +942,229 @@ + // 新的地图功能事件处理 + function onMapFeaturesChange() { + var selectElement = document.getElementById('mapFeatures'); + var value = selectElement.value; + + switch(value) { + case 'toggle_labels': + showDeviceId = !showDeviceId; + vectorLayer.changed(); + break; + case 'toggle_cluster': + showCluster = !showCluster; + var zoom = map.getView().getZoom(); + if (showCluster) { + if (zoom >= maxZoomForClustering) { + clusterLayer.setVisible(false); + vectorLayer.setVisible(true); + } else { + clusterLayer.setVisible(true); + vectorLayer.setVisible(false); + } + } else { + clusterLayer.setVisible(false); + vectorLayer.setVisible(true); + } + break; + case 'measure_distance': + startMeasuring(); + break; + case 'clear_measure': + clearMeasurements(); + break; + } + + // 重置下拉框到默认状态 + selectElement.value = ''; + } + + // 测距功能 + function startMeasuring() { + if (measuring) return; + + measuring = true; + + // 创建测距图层 + if (!measureSource) { + measureSource = new ol.source.Vector(); + measureVector = new ol.layer.Vector({ + source: measureSource, + style: new ol.style.Style({ + fill: new ol.style.Fill({ + color: 'rgba(255, 255, 255, 0.2)' + }), + stroke: new ol.style.Stroke({ + color: '#ffcc33', + width: 2 + }), + image: new ol.style.Circle({ + radius: 7, + fill: new ol.style.Fill({ + color: '#ffcc33' + }) + }) + }) + }); + map.addLayer(measureVector); + } + + // 创建绘制交互 + draw = new ol.interaction.Draw({ + source: measureSource, + type: 'LineString', + style: new ol.style.Style({ + fill: new ol.style.Fill({ + color: 'rgba(255, 255, 255, 0.2)' + }), + stroke: new ol.style.Stroke({ + color: 'rgba(0, 0, 0, 0.5)', + lineDash: [10, 10], + width: 2 + }), + image: new ol.style.Circle({ + radius: 5, + stroke: new ol.style.Stroke({ + color: 'rgba(0, 0, 0, 0.7)' + }), + fill: new ol.style.Fill({ + color: 'rgba(255, 255, 255, 0.2)' + }) + }) + }) + }); + + map.addInteraction(draw); + + createMeasureTooltip(); + createHelpTooltip(); + + var listener; + draw.on('drawstart', function(evt) { + var sketch = evt.feature; + var tooltipCoord = evt.coordinate; + + listener = sketch.getGeometry().on('change', function(evt) { + var geom = evt.target; + var output; + if (geom instanceof ol.geom.LineString) { + output = formatLength(geom); + tooltipCoord = geom.getLastCoordinate(); + } + measureTooltipElement.innerHTML = output; + measureTooltip.setPosition(tooltipCoord); + }); + }); + + draw.on('drawend', function() { + measureTooltipElement.className = 'measure-tooltip measure-tooltip-static'; + measureTooltip.setOffset([0, -7]); + measureTooltipElement = null; + createMeasureTooltip(); + ol.Observable.unByKey(listener); + + // 结束测距 + map.removeInteraction(draw); + measuring = false; + + // 移除帮助提示 + if (helpTooltip) { + map.removeOverlay(helpTooltip); + helpTooltip = null; + helpTooltipElement = null; + } + }); + } + + function clearMeasurements() { + if (measureSource) { + measureSource.clear(); + } + + if (draw) { + map.removeInteraction(draw); + draw = null; + } + + measuring = false; + + // 清除所有测距相关的覆盖物 + var overlays = map.getOverlays().getArray().slice(); + overlays.forEach(function(overlay) { + if (overlay.getElement() && + (overlay.getElement().classList.contains('measure-tooltip') || + overlay.getElement().classList.contains('help-tooltip'))) { + map.removeOverlay(overlay); + } + }); + + measureTooltip = null; + measureTooltipElement = null; + helpTooltip = null; + helpTooltipElement = null; + } + + function createMeasureTooltip() { + if (measureTooltipElement) { + measureTooltipElement.parentNode.removeChild(measureTooltipElement); + } + measureTooltipElement = document.createElement('div'); + measureTooltipElement.className = 'measure-tooltip measure-tooltip-measure'; + measureTooltip = new ol.Overlay({ + element: measureTooltipElement, + offset: [0, -15], + positioning: 'bottom-center' + }); + map.addOverlay(measureTooltip); + } + + function createHelpTooltip() { + if (helpTooltipElement) { + helpTooltipElement.parentNode.removeChild(helpTooltipElement); + } + helpTooltipElement = document.createElement('div'); + helpTooltipElement.className = 'measure-tooltip help-tooltip'; + helpTooltipElement.innerHTML = '点击开始测距,双击结束'; + helpTooltip = new ol.Overlay({ + element: helpTooltipElement, + offset: [15, 0], + positioning: 'center-left' + }); + map.addOverlay(helpTooltip); + } + + function formatLength(line) { + var length = ol.Sphere.getLength(line); + var output; + if (length > 100) { + output = (Math.round(length / 1000 * 100) / 100) + ' km'; + } else { + output = (Math.round(length * 100) / 100) + ' m'; + } + return output; + } + + // 比例尺更新功能 + function updateScale() { + var view = map.getView(); + var resolution = view.getResolution(); + var units = view.getProjection().getUnits(); + var dpi = 25.4 / 0.28; + var mpu = ol.proj.METERS_PER_UNIT[units]; + var scale = resolution * mpu * 39.37 * dpi; + + if (scale >= 9500 && scale <= 950000) { + scale = Math.round(scale / 1000) * 1000; + } else if (scale >= 950000) { + scale = Math.round(scale / 100000) * 100000; + } else { + scale = Math.round(scale); + } + + document.getElementById('map-scale').textContent = '比例尺 1:' + scale.toLocaleString(); + } + function onMapTypeChange() { var mapType = document.getElementById('mapTypeSelectNew').value; switchMapType(mapType); @@ -1032,7 +1227,7 @@ navigator.geolocation.getCurrentPosition(function(position) { var lon = position.coords.longitude; var lat = position.coords.latitude; - var currentMapType = document.getElementById('mapTypeSelect').value; + var currentMapType = document.getElementById('mapTypeSelectNew').value; var coordinates; if (currentMapType === 'amap' || currentMapType === 'amap_satellite') { @@ -1390,47 +1585,6 @@ showWarning2(); } } - - function onDisplayOptionsChange() { - var optionValue = document.getElementById('displayOptions').value; - - switch(optionValue) { - case 'both': - showDeviceId = true; - showCluster = true; - break; - case 'device': - showDeviceId = true; - showCluster = false; - break; - case 'cluster': - showDeviceId = false; - showCluster = true; - break; - case 'none': - showDeviceId = false; - showCluster = false; - break; - } - - // 更新图层可见性 - var zoom = map.getView().getZoom(); - if (showCluster) { - if (zoom >= maxZoomForClustering) { - clusterLayer.setVisible(false); - vectorLayer.setVisible(true); - } else { - clusterLayer.setVisible(true); - vectorLayer.setVisible(false); - } - } else { - clusterLayer.setVisible(false); - vectorLayer.setVisible(true); - } - - // 强制更新样式 - vectorLayer.changed(); - }