openlayers绘制线段和多边形
效果
演示地址
https://codesandbox.io/s/ol-measure-u3yob
源码
用 ts编写,如需要引用到js请编译
//绘制图形
this.measure.start({ type: GeometryType.POLYGON })
//重新绘制
this.measure.restart({ type: GeometryType.POLYGON })
//销毁
this.measure.destoryed({ type: GeometryType.POLYGON })
//绘制工具
import { MapBrowserEvent, Overlay, Map, Feature } from "ol";
import { Options as OverlayOptions } from "ol/Overlay";
import { Draw } from "ol/interaction";
import LineString from "ol/geom/LineString";
import Polygon from "ol/geom/Polygon";
import VectorSource from "ol/source/Vector";
import { Options, DrawEvent } from "ol/interaction/Draw";
import OverlayPositioning from "ol/OverlayPositioning";
import { Coordinate } from "ol/coordinate";
import Point from "ol/geom/Point";
import { Text, Fill, Style, Stroke } from "ol/style";
import TextPlacement from "ol/style/TextPlacement";
import { unByKey } from "ol/Observable";
import { EventsKey } from "ol/events";
import { getArea, getLength } from "ol/sphere";
import CircleStyle from "ol/style/Circle";
// import { drawStyle } from './style';
const drawStyle = new Style({
fill: new Fill({
color: "rgba(255, 255, 255, 0.6)"
}),
stroke: new Stroke({
color: "blue",
// lineDash: [10, 10],
width: 1.5
}),
image: new CircleStyle({
radius: 5,
stroke: new Stroke({
color: "transparent"
}),
fill: new Fill({
color: "rgba(255, 255, 255, 0.2)"
})
})
});
interface IMEASUREDRAW {
instance: Draw;
// sketch:
continueMsg: string;
helpTooltipElement: HTMLElement;
helpTooltip: Overlay;
pointerMoveHandler(evt: MapBrowserEvent): void;
createHelpTooltip(): void;
drawstart(evt: DrawEvent): void;
drawend(evt: DrawEvent): void;
// cancelInteraction(): void;
// static formatLength(line: LineString): string;
// static formatArea(polygon: Polygon): string;
// static mouseout(): void;
}
export default class MeasureDraw implements IMEASUREDRAW {
public instance: Draw;
public status: "drawing" | "idle" = "idle";
public continueMsg: string = "单击点击继续,双击结束绘制";
helpTooltip: Overlay;
helpTooltipElement: HTMLElement;
listeners: EventsKey[] = [];
map: Map;
source: VectorSource;
mouseoutKey: any;
constructor(source: VectorSource, map: Map) {
this.map = map;
this.source = source;
// this.destoryed();
}
start(options: Options) {
if (this.status === "drawing")
return window.alert("请结束当前绘制,采能启用");
this.createHelpTooltip();
/** 创建draw交互 */
this.instance = new Draw({
source: this.source,
style: drawStyle,
...options
});
this.map.addInteraction(this.instance);
this.listeners.push(
...[
this.instance.on("drawstart", this.drawstart.bind(this)),
this.instance.on("drawend", this.drawend.bind(this))
]
);
this.listeners.push(
this.map.on("pointermove", this.pointerMoveHandler.bind(this))
);
this.mouseoutKey = this.mouseout.bind(this);
this.map.getViewport().addEventListener("mouseout", this.mouseoutKey);
this.status = "drawing";
}
restart(options: Options) {
this.reset();
this.start(options);
}
pointerMoveHandler(evt: MapBrowserEvent): void {
if (evt.dragging) {
return;
}
const helpMsg: string = this.continueMsg || "单点击地图进行绘制";
// if (sketch) {
// const geom = sketch.getGeometry();
// if (geom instanceof Polygon) {
// helpMsg = continuePolygonMsg;
// } else if (geom instanceof LineString) {
// helpMsg = continueLineMsg;
// }
// }
this.helpTooltipElement.innerHTML = helpMsg;
this.helpTooltip.setPosition(evt.coordinate);
this.helpTooltipElement.classList.remove("hidden");
}
/** 创建工具使用提示消息 */
createHelpTooltip(): void {
if (this.helpTooltipElement) {
this.helpTooltipElement.parentNode.removeChild(this.helpTooltipElement);
}
this.helpTooltipElement = document.createElement("div");
this.helpTooltipElement.className = "ol-tooltip hidden";
this.helpTooltip = new Overlay({
element: this.helpTooltipElement,
offset: [15, 0],
positioning: OverlayPositioning.CENTER_LEFT
});
this.map.addOverlay(this.helpTooltip);
}
drawstart(evt: DrawEvent): void {
// set sketch
const sketch = evt.feature;
let tooltipCoord: Coordinate = null;
const changekey = sketch.getGeometry().on("change", e => {
const style = drawStyle.clone();
const geom = e.target;
let output;
let offsetX = 0;
if (geom instanceof Polygon) {
output = MeasureDraw.formatArea(geom);
tooltipCoord = geom.getInteriorPoint().getCoordinates();
} else if (geom instanceof LineString) {
output = MeasureDraw.formatLength(geom);
tooltipCoord = geom.getLastCoordinate();
offsetX = -50;
style.setGeometry(new Point(tooltipCoord));
}
style.setText(
new Text({
font: "14px Arial",
text: output,
offsetX,
// textAlign: ,
placement: TextPlacement.POINT,
overflow: true,
backgroundFill: new Fill({
color: "rgba(255,255,255,0.4)"
})
})
);
sketch.setStyle([drawStyle.clone(), style]);
});
this.listeners.push(changekey);
}
drawend(evt: DrawEvent): void {
const geom = evt.feature.getGeometry();
let lastPos;
if (geom instanceof Polygon) {
console.log(geom.getCoordinates(), geom.getCoordinates(true));
// eslint-disable-next-line prefer-destructuring
lastPos = geom.getCoordinates(true)[0][1];
} else {
lastPos = (geom as any).getLastCoordinate();
}
this.createCancelOverlayer(
{ position: lastPos },
"measureOverlay",
evt.feature
);
this.reset();
// while (this.listeners.length) {
// const eventsKey = this.listeners.pop();
// unByKey(eventsKey);
// }
// this.map.removeInteraction(this.instance);
// this.instance = null;
// this.map.removeOverlay(this.helpTooltip);
// this.helpTooltip = null;
// this.helpTooltipElement = null;
// this.map = null;
// this.listeners = [];
// this.cancelInteraction();
}
reset() {
this.status = "idle";
while (this.listeners.length) {
const eventsKey = this.listeners.pop();
unByKey(eventsKey);
}
this.map.getViewport().removeEventListener("mouseout", this.mouseoutKey);
this.mouseoutKey = null;
this.map.removeInteraction(this.instance);
this.instance = null;
this.map.removeOverlay(this.helpTooltip);
this.helpTooltip = null;
this.helpTooltipElement = null;
}
destoryed(): void {
this.reset();
this.map = null;
this.source = null;
}
static formatLength(line: LineString): string {
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;
}
static formatArea(polygon: Polygon): string {
const area = getArea(polygon);
let output;
if (area > 10000) {
output = `${Math.round((area / 1000000) * 100) / 100} km ²`;
} else {
output = `${Math.round(area * 100) / 100} m ²`;
}
return output;
}
createCancelOverlayer(
options: OverlayOptions,
name: string,
feature: Feature
): void {
let el = document.createElement("div");
el.style.cursor = "pointer";
el.title = "关闭";
el.innerHTML = `
<svg t="1588921664969" class="icon" viewBox="0 0 1024 1024" style="fill: red" version="1.1" xmlns="http://www.w3.org/2000/svg" p-id="5187" width="24" height="24"><path d="M512 960C265.6 960 64 758.4 64 512S265.6 64 512 64s448 201.6 448 448-201.6 448-448 448z m0-832C300.8 128 128 300.8 128 512s172.8 384 384 384 384-172.8 384-384S723.2 128 512 128z" p-id="5188"></path><path d="M672 704c-8 0-16-3.2-22.4-9.6l-320-320c-12.8-12.8-12.8-32 0-44.8 12.8-12.8 32-12.8 44.8 0l320 320c12.8 12.8 12.8 32 0 44.8-6.4 6.4-14.4 9.6-22.4 9.6z" p-id="5189"></path><path d="M352 704c-8 0-16-3.2-22.4-9.6-12.8-12.8-12.8-32 0-44.8l320-320c12.8-12.8 32-12.8 44.8 0 12.8 12.8 12.8 32 0 44.8l-320 320c-6.4 6.4-14.4 9.6-22.4 9.6z" p-id="5190"></path></svg>
`;
let overlayer = new Overlay({
element: el,
positioning: OverlayPositioning.CENTER_CENTER,
...options
});
el.onclick = () => {
this.map.removeOverlay(overlayer);
this.source.removeFeature(overlayer.get("feature"));
overlayer.set("name", null);
overlayer.set("feature", null);
overlayer.dispose();
el = null;
overlayer = null;
};
overlayer.set("name", name);
overlayer.set("feature", feature);
this.map.addOverlay(overlayer);
// return overlayer;
}
mouseout(): void {
if (this.helpTooltipElement) {
this.helpTooltipElement.classList.add("hidden");
} else {
console.log("错误");
}
}
}