如何调整Geojson多边形的大小/缩放

时间:2019-04-18 23:26:29

标签: javascript mapbox-gl-js turfjs

我目前正在建立不同的geojson多边形交互。 我的阻止者正在构建此算法,该算法允许使用onMouseDown方法缩放多边形的大小。

它是使用vanilla.js构建的,并使用npm进行依赖。

import distance from "@turf/distance";
import centroid from "@turf/centroid";
import transformScale from "@turf/transform-scale";
import EventEmitter from "events";
const emitter = new EventEmitter();

const ScaleMode = {
  scalestart(selectedFeature, originalCenter) {},
  scaling(selectedFeature, originalCenter, lastMouseDown) {},
  scaleend(selectedFeature) {},

  onSetup: function(opts) {
    var state = {};

    emitter.addListener(
      "scalestart",
      function() {
        this.scalestart(state.selectedFeature, state.originalCenter);
      }.bind(this)
    );
    emitter.addListener(
      "scaling",
      function() {
        this.scaling(
          state.selectedFeature,
          state.originalCenter,
          state.lastMouseDownLngLat
        );
      }.bind(this)
    );
    emitter.addListener(
      "scaleend",
      function() {
        this.scaleend(state.selectedFeature, state.lastMouseDownLngLat);
      }.bind(this)
    );

    state.selectedFeature = opts.selectedFeature || false;
    state.lastMouseDownLngLat = false;
    state.originalCenter = false;
    state.mode = "scale" || false;
    return state;
  },
  toDisplayFeatures(state, geojson, display) {
    display(geojson);
  },
  onMouseDown: (state, e) => {
    if (e.featureTarget) {
      // calculate the polygon center
      state.polyCenter = turf.centroid(e.featureTarget);
      const polyCoordinates = state.polyCenter.geometry.coordinates;
      const poly = turf.polygon(PolyData);
      console.log(poly);
      const scaledPoly = turf.transformScale(poly, 3);
      console.log(poly);

      // scaling
      state.scaledPoly = transformScale(poly, 3);

      // disable on drag map over the polygon
      e.target["dragPan"].disable();
    }
  }
};

export default ScaleMode;

我希望能够使用onMouseDown / onMouseUp / onDrag方法来增加多边形的坐标。

演示:https://codesandbox.io/s/54qv8x244n

1 个答案:

答案 0 :(得分:1)

这里是mapbox-gl-rotate-mode处理scaleTransform的副本:

const distance = require("@turf/distance").default;
const centroid = require("@turf/centroid").default;
const transformScale = require("@turf/transform-scale").default;
const EventEmitter = require("events");
const emitter = new EventEmitter();

var ScaleMode = {
  scalestart: function() {},
  scaling: function() {},
  scaleend: function() {},

  onSetup: function(opts) {
    var state = {};

    emitter.addListener(
      "scalestart",
      function() {
        this.scalestart(state.selectedFeature, state.originalCenter);
      }.bind(this)
    );
    emitter.addListener(
      "scaling",
      function() {
        this.scaling(
          state.selectedFeature,
          state.originalCenter,
          state.scaleFactor
        );
      }.bind(this)
    );
    emitter.addListener(
      "scaleend",
      function() {
        this.scaleend(state.selectedFeature, state.scaleFactor);
      }.bind(this)
    );

    state.selectedFeature = opts.selectedFeature || undefined;
    state.scaleFactor = 1;
    state.originalCenter = undefined;
    state.mode = "scale";
    return state;
  },

  onMouseDown: function(state, e) {
    if (e.featureTarget) {
      if (this._ctx.api.get(e.featureTarget.properties.id)) {
        e.target["dragPan"].disable();
        state.selectedFeature = this._ctx.api.get(
          e.featureTarget.properties.id
        );
        state.originalCenter = centroid(e.featureTarget);
        state.originalFeature = e.featureTarget;
        state.originalDistance = Math.max(
          distance(state.originalCenter, [e.lngLat.lng, e.lngLat.lat]),
          0.1
        );
        emitter.emit("scalestart");
      }
    }
    return state;
  },

  toDisplayFeatures: function(state, geojson, display) {
    display(geojson);
  },

  onDrag: function(state, e) {
    if (state.selectedFeature && state.mode) {
      if (state.mode === "scale") {
        switch (state.originalFeature.properties["meta:type"]) {
          case "Point":
            break;
          case "LineString":
          case "Polygon":
          case "MultiLineString":
          case "MultiPolygon":
            state.scaleFactor =
              distance(state.originalCenter, [e.lngLat.lng, e.lngLat.lat]) /
                state.originalDistance || 1;
            break;
          default:
            return;
        }
        emitter.emit("scaling");
        state.selectedFeature.geometry = transformScale(
          state.originalFeature,
          state.scaleFactor
        ).geometry;
        this._ctx.api.add(state.selectedFeature);
      }
    }
  },

  onMouseUp: function(state, e) {
    e.target["dragPan"].enable();
    emitter.emit("scaleend");
    state.selectedFeature = undefined;
    state.scaleFactor = undefined;
    state.originalCenter = undefined;
    state.originalDistance = undefined;
    return state;
  }
};

module.exports = ScaleMode;

我将其包装为npm包,现在可以像旋转插件一样使用它了:

npm i mapbox-gl-scale-mode

working here看到它。