I'm currently building different geojson polygon interactions. My blocker is building this algorithm that allows to scale the size of the polygon with onMouseDown method.
It was built with vanilla.js and use npm for dependencies.
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;
I want to be able to increase the coordinates of the polygon using onMouseDown/onMouseUp/onDrag methods.
Here's a clone of mapbox-gl-rotate-mode
handling 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;
I wrapped it up as a npm package and you can now use it exactly like the rotate plugin:
npm i mapbox-gl-scale-mode
See it working here .
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.