要求
主要有距离和面积测量,绘制的时候清空上一次绘制的图形。做到距离和面积切换
实现
- html
<label class="m-l-20 measure">
<span
class="measure-item"
:class="{ 'measure-active': ruleType === 'line' }"
@click="setRule('line')"
><icon-font type="icon--Ruler"></icon-font
></span>
<span
class="m-l-10 measure-item"
:class="{ 'measure-active': ruleType === 'area' }"
@click="setRule('area')"
><icon-font type="icon-rule-area"></icon-font
></span>
</label>
- ts 这里的style是画图时显示的样式 不是画完图后的样式
// 这个是画图时显示的样式 不是画完图后的样式
const MeasureStyle = new Style({
fill: new Fill({
color: 'rgba(255, 255, 255, 0.2)'
}),
stroke: new Stroke({
color: 'rgba(0, 0, 0, 0.5)',
lineDash: [10, 10],
width: 2,
}),
image: new Circle({
radius: 5,
stroke: new Stroke({
color: 'rgba(0, 0, 0, 0.7)',
}),
fill: new Fill({
color: 'rgba(255, 255, 255, 0.2)',
}),
})
})
measureVectorLayer这里的style时画完图后的样式
const drawSource = new VectorSource();
// 这里的style时画完图后的样式
const measureVectorLayer = new VectorLayer({
source: drawSource,
style: new Style({
stroke: new Stroke({
color: "#ffcc33",
width: 2,
}),
}),
});
state.map.addLayer(measureVectorLayer)
// 测量
const ruleType = ref(null);
let helpTooltipElement: HTMLElement | null;
let measureTooltipElement: HTMLElement | null;
let helpTooltip: Overlay, measureTooltip: Overlay;
let sketch: Feature | null;
let draw = ref();
const createMeasureDom = () => {
helpTooltipElement = document.createElement("div");
helpTooltipElement.className = "ol-tooltip hidden";
helpTooltip = new Overlay({
element: helpTooltipElement,
offset: [15, 0],
positioning: "center-left",
});
measureTooltipElement = document.createElement("div");
measureTooltipElement.className = "ol-tooltip ol-tooltip-measure";
measureTooltip = new Overlay({
element: measureTooltipElement,
offset: [0, -15],
positioning: "bottom-center",
stopEvent: false,
insertFirst: false,
});
state.map.addOverlay(measureTooltip);
state.map.addOverlay(helpTooltip);
};
const formatLength = (line) => {
const length = 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;
};
const formatArea = (polygon) => {
const area = getArea(polygon);
let output;
if (area > 10000)
output = Math.round((area / 1000000) * 100) / 100 + " km<sup>2</sup>";
else output = Math.round(area * 100) / 100 + " m<sup>2</sup>";
return output;
};
let listener;
const drawStart = (evt) => {
sketch = evt.feature;
drawSource.clear();
let tooltipCoord;
if (!sketch) return;
listener = sketch.getGeometry()?.on("change", (sevt) => {
const geom = sevt.target;
let output;
if (geom instanceof Polygon) {
output = formatArea(geom);
tooltipCoord = geom.getInteriorPoint().getCoordinates();
} else if (geom instanceof LineString) {
output = formatLength(geom);
tooltipCoord = geom.getLastCoordinate();
}
measureTooltipElement!.innerHTML = output;
measureTooltip.setPosition(tooltipCoord);
});
};
const drawEnd = () => {
measureTooltipElement!.className = "ol-tooltip ol-tooltip-static";
measureTooltip.setOffset([0, -7]);
sketch = null;
unByKey(listener);
};
const addInteraction = (ruleType) => {
const type = ruleType === "line" ? "LineString" : "Polygon";
draw.value = new Draw({
source: drawSource,
type: type,
style: MeasureStyle,
});
state.map.addInteraction(draw.value);
draw.value.on("drawstart", drawStart);
draw.value.on("drawend", drawEnd);
};
const setRule = (type) => {
state.map.removeInteraction(draw.value);
if (ruleType.value === type) {
ruleType.value = null;
return;
} else ruleType.value = type;
addInteraction(type);
};
const pointerMoveHandle = (evt) => {
if (evt.dragging || !ruleType.value) {
helpTooltipElement!.classList.add("hidden");
return;
}
let helpMsg = "点击开始测量";
if (sketch) {
helpMsg = "点击继续画";
}
helpTooltipElement!.innerHTML = helpMsg;
helpTooltip.setPosition(evt.coordinate);
helpTooltipElement!.classList.remove("hidden");
};
const listenHandle = () => {
state.map.getView().addEventListener("mouseout", () => {
helpTooltipElement!.classList.add("hidden");
});
state.map.on("pointermove", pointerMoveHandle);
};
- css
// 测量样式
.measure {
&-item {
margin: 0 10px;
padding: 0 4px;
height: 30px;
line-height: 30px;
font-size: 20px;
color: #333;
cursor: pointer;
}
.measure-active {
background: rgba(51, 51, 51, 0.5);
}
}
.ol-tooltip {
position: relative;
border-radius: 4px;
padding: 4px 8px;
opacity: 0.7;
white-space: nowrap;
font-size: 12px;
user-select: none;
}
.ol-tooltip.hidden {
display: 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;
}
注意
draw不能在vue3 setup()
组件直接设置let draw:Draw
,否则removeInteraction
会移除失败。设置let draw = ref()
不用return
可以正常使用。