openlayers 面积和周长的计算

433 阅读1分钟

效果展示

GIF.gif

代码

<template>
  <div>
    <div style="margin-bottom: 20px">
      <el-select v-model="type" placeholder="请选择" @change="changType">
        <el-option
          v-for="item in options"
          :key="item.value"
          :label="item.label"
          :value="item.value"
        >
        </el-option>
      </el-select>
    </div>
    <div id="Measure" class="dynamic-component-demo"></div>
  </div>
</template>

<script>
import { getArea, getLength } from "ol/sphere";
/**
 * Format length output.
 * @param {LineString} line The line.
 * @return {string} The formatted length.
 */
const formatLength = function (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;
};

/**
 * Format area output.
 * @param {Polygon} polygon The polygon.
 * @return {string} Formatted area.
 */
const formatArea = function (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;
};
import Map from "ol/Map";
import View from "ol/View";
import { transform } from "ol/proj";
import Overlay from "ol/Overlay";
import { gaodeMapLayer } from "@/utils/MapLayer.js";
import { Vector as VectorSource } from "ol/source";
import { Vector as VectorLayer } from "ol/layer";
import { Circle, Fill, Stroke, Style } from "ol/style";
import { unByKey } from "ol/Observable";
import Draw from "ol/interaction/Draw";
import { LineString, Polygon } from "ol/geom";
export default {
  name: "Measure",
  data() {
    return {
      type: "LineString",
      options: [
        { label: "周长", value: "LineString" },
        { label: "面积", value: "Polygon" },
      ],
      map: null,
      vector: null,
      sketch: null,
      helpTooltipElement: null,
      draw: null,
      listener: null,
      measureTooltip: null,
      measureTooltipElement: null,
      source: new VectorSource(),
      continueLineMsg: "Click to continue drawing the line",
      continuePolygonMsg: "Click to continue drawing the polygon",
    };
  },
  mounted() {
    this._initMap();
  },
  methods: {
    changType(val) {
      let { draw, map } = this;
      map.removeInteraction(draw);
      this.addInteraction(map);
    },
    _initMap() {
      const vector = new VectorLayer({
        source: this.source,
        style: new Style({
          fill: new Fill({
            color: "rgba(255, 255, 255, 0.2)",
          }),
          stroke: new Stroke({
            color: "#409eff",
            width: 5,
          }),
          image: new Circle({
            radius: 7,
            fill: new Fill({
              color: "#409eff",
            }),
          }),
        }),
      });
      const map = new Map({
        // 设置地图图层
        layers: [gaodeMapLayer, vector],
        // 设置显示地图的视图
        view: new View({
          center: transform([104.06, 30.67], "EPSG:4326", "EPSG:3857"),
          zoom: 9,
          minZoom: 1,
          maxZoom: 21,
          //  projection: "EPSG:4326",
          rotation: 0,
        }),
        // 让id为map的div作为地图的容器
        target: "Measure",
      });
      /// map.
      this.createMeasureTooltip(map);
      this.createHelpTooltip(map);
      this.addInteraction(map);
      map.on("pointermove", this.pointerMoveHandler);
      //  let { helpTooltipElement } = this;
      map.getViewport().addEventListener("mouseout", () => {
        this.helpTooltipElement.classList.add("hidden");
      });
      this.map = map;
    },
    createMeasureTooltip(map) {
      let { measureTooltipElement } = this;
      if (measureTooltipElement) {
        measureTooltipElement.parentNode.removeChild(measureTooltipElement);
      }
      let measure_tooltip_element = document.createElement("div");
      measure_tooltip_element.className = "ol-tooltip ol-tooltip-measure";
      let measure_tool_tip = new Overlay({
        element: measure_tooltip_element,
        offset: [0, -15],
        positioning: "bottom-center",
        stopEvent: false,
        insertFirst: false,
      });
      this.measureTooltipElement = measure_tooltip_element;
      this.measureTooltip = measure_tool_tip;
      console.log(this.measureTooltipElement, "createMeasureTooltip");
      //  debugger
      //  return measure_tool_tip;
      map.addOverlay(measure_tool_tip);
    },
    createHelpTooltip(map) {
      if (this.helpTooltipElement) {
        this.helpTooltipElement.parentNode.removeChild(this.helpTooltipElement);
      }
      let help_tooltip_element = document.createElement("div");
      help_tooltip_element.className = "ol-tooltip hidden";
      let help_tool_tip = new Overlay({
        element: help_tooltip_element,
        offset: [15, 0],
        positioning: "center-left",
      });
      this.helpTooltipElement = help_tooltip_element;
      this.helpTooltip = help_tool_tip;
      // return help_tool_tip;
      map.addOverlay(help_tool_tip);
      // this.helpTooltip = Tooltip
    },
    addInteraction(map) {
      let _this = this;
      const draw = new Draw({
        source: this.source,
        type: this.type,
        style: 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(255, 0, 0, 0.9)",
            }),
            fill: new Fill({
              color: "rgba(0, 0, 0, 0)",
            }),
          }),
        }),
      });
      draw.on("drawstart", (evt) => {
        // set sketch
        _this.sketch = evt.feature;
        let tooltipCoord = evt.coordinate;
        _this.listener = _this.sketch
          .getGeometry()
          .on("change", function (evt) {
            const geom = evt.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();
            }
            _this.measureTooltipElement.innerHTML = output;
            _this.measureTooltip.setPosition(tooltipCoord);
          });
      });
      draw.on("drawend", () => {
        _this.measureTooltipElement.className = "ol-tooltip ol-tooltip-static";
        _this.measureTooltip.setOffset([0, -7]);
        // unset sketch
        _this.sketch = null;
        // unset tooltip so that a new one can be created
        _this.measureTooltipElement = null;
        _this.createMeasureTooltip(map);
        unByKey(_this.listener);
      });
      map.addInteraction(draw);
      this.draw = draw;
    },
    pointerMoveHandler(evt) {
      if (evt.dragging) {
        //拖到地图的时候
        console.log("拖到地图的时候");
        return;
      }
      let helpMsg = "Click to start drawing";
      //console.log(evt, "evt")
      if (this.sketch) {
        const geom = this.sketch.getGeometry();
        if (geom instanceof Polygon) {
          helpMsg = this.continuePolygonMsg;
        } else if (geom instanceof LineString) {
          helpMsg = this.continueLineMsg;
        }
      }
      this.helpTooltipElement.innerHTML = helpMsg;
      this.helpTooltip.setPosition(evt.coordinate);
      this.helpTooltipElement.classList.remove("hidden");
    },
  },
};
</script>

<style>
.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: #409eff;
  color: #fff;
  font-weight: bolder;
  border: 1px solid white;
  opacity: 1;
}

.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: #409eff;
}
</style>