參考文章
https://openlayers.org/en/latest/examples/measure.html
跟官網的範例比較,我有把一些我認為比較會會的地方給抽調,因為範例中是增加了下拉選單可以選擇多邊形或是線段的繪製
我認為主要的概念是
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是參考官網的,主要也要回應我提到的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