参考文章
https://openlayers.org/en/latest/examples/measure.html
跟官网的範例比较,我有把一些我认为比较会会的地方给抽调,因为範例中是增加了下拉选单可以选择多边形或是线段的绘製
我认为主要的概念是
建立绘图专用的的layerInteraction是要与绘图专用layer共用source (这点很重要)openlayers中可以建立监听事件,API中可以查询参考此範例中就用上Geometry的change与Draw的drawstart、drawendOverlay是一个可以在地图上放置HTML标记的功能我自己是这样理解,如果大家有其他想法欢迎分享这可能有点太早说了,但就......刚好想讲这个主题JS
const map = new ol.Map({ layers: [ new ol.layer.Tile({ source: new ol.source.OSM() }) ], target: 'map', view: new ol.View({ projection: "EPSG:3857", center: ol.proj.fromLonLat([120.846642, 23.488793]), zoom: 7.5, maxZoom: 20, minZoom: 5, enableRotation: false, }), controls: []});// 1.source共用const source = new ol.source.Vector();const vector = new ol.layer.Vector({ source: source, style: { 'fill-color': 'rgba(255, 255, 255, 0.2)', 'stroke-color': '#ffcc33', 'stroke-width': 2, 'circle-radius': 7, 'circle-fill-color': '#ffcc33', },});map.addLayer(vector)// Currently drawn feature.let sketch;// The measure tooltip element.let measureTooltipElement;// Overlay to show the measurement.let measureTooltip;// 计算距离const formatLength = function (line) { const length = ol.sphere.getLength(line); let output; if (length > 100) { output = Math.round((length / 1000) * 100) / 100 + ' ' + 'km'; } else { output = Math.round(length * 100) / 100 + ' ' + 'm'; } return output;};// 增加互动function addInteraction() { let draw = new ol.interaction.Draw({ // 1.source共用 source: source, 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(); let listener; draw.on('drawstart', function (evt) { // set sketch sketch = evt.feature; let tooltipCoord = evt.coordinate; listener = sketch.getGeometry().on('change', function (evt) { const geom = evt.target; let output = formatLength(geom); tooltipCoord = geom.getLastCoordinate(); measureTooltipElement.innerHTML = output; // 显示计算完的长度 measureTooltip.setPosition(tooltipCoord); // 更新提示框的位置 }); }); draw.on('drawend', function () { measureTooltipElement.className = 'ol-tooltip ol-tooltip-static'; measureTooltip.setOffset([0, -7]); // unset sketch sketch = null; // unset tooltip so that a new one can be created measureTooltipElement = null; createMeasureTooltip(); ol.Observable.unByKey(listener); });}// 显示测量距离function createMeasureTooltip() { if (measureTooltipElement) { measureTooltipElement.parentNode.removeChild(measureTooltipElement); } measureTooltipElement = document.createElement('div'); measureTooltipElement.className = 'ol-tooltip ol-tooltip-measure'; measureTooltip = new ol.Overlay({ element: measureTooltipElement, offset: [0, -15], positioning: 'bottom-center', stopEvent: false, insertFirst: false, }); map.addOverlay(measureTooltip);}addInteraction();
CSS
这段css是参考官网的,主要也要回应我提到的Overlay,因为是HTML元素放到地图上,所以可以透过css来控制
createMeasureTooltip的function中特别指定自己想要客製化的class名称,如此一来可以更多元的操控Overlay的样子
html,body { margin: 0; padding: 0;}#map { width: 100vw; height: 100vh;}.ol-tooltip { position: relative; background: rgba(0, 0, 0, 0.5); border-radius: 4px; color: white; padding: 4px 8px; opacity: 0.7; white-space: nowrap; font-size: 12px; cursor: default; user-select: none;}.ol-tooltip-measure { opacity: 1; font-weight: bold;}.ol-tooltip-static { background-color: #ffcc33; color: black; border: 1px solid white;}.ol-tooltip-measure:before,.ol-tooltip-static:before { border-top: 6px solid rgba(0, 0, 0, 0.5); border-right: 6px solid transparent; border-left: 6px solid transparent; content: ""; position: absolute; bottom: -6px; margin-left: -7px; left: 50%;}.ol-tooltip-static:before { border-top-color: #ffcc33;}
参考网址
https://github.com/weijung0923/learning-openlayers-micromastery/tree/day08