openlayers绘制线段和多边形

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("错误");
    }
  }
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值