Merge pull request #13455 from MoonE/snap-load
Improve Snap interaction performance
This commit is contained in:
+6
-9
@@ -16,15 +16,6 @@ tags: "draw, edit, modify, vector, snap"
|
|||||||
<input type="radio" name="interaction" value="draw" id="draw" checked>
|
<input type="radio" name="interaction" value="draw" id="draw" checked>
|
||||||
Draw
|
Draw
|
||||||
</label>
|
</label>
|
||||||
</div>
|
|
||||||
<div class="radio">
|
|
||||||
<label>
|
|
||||||
<input type="radio" name="interaction" value="modify">
|
|
||||||
Modify
|
|
||||||
</label>
|
|
||||||
</div>
|
|
||||||
<div class="form-group">
|
|
||||||
<label for="draw-type">Draw type </label>
|
|
||||||
<select name="draw-type" id="draw-type">
|
<select name="draw-type" id="draw-type">
|
||||||
<option value="Point">Point</option>
|
<option value="Point">Point</option>
|
||||||
<option value="LineString">LineString</option>
|
<option value="LineString">LineString</option>
|
||||||
@@ -32,4 +23,10 @@ tags: "draw, edit, modify, vector, snap"
|
|||||||
<option value="Circle">Circle</option>
|
<option value="Circle">Circle</option>
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="radio">
|
||||||
|
<label>
|
||||||
|
<input type="radio" name="interaction" value="modify">
|
||||||
|
Modify
|
||||||
|
</label>
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
|
|||||||
+14
-14
@@ -94,18 +94,16 @@ const ExampleDraw = {
|
|||||||
source: vector.getSource(),
|
source: vector.getSource(),
|
||||||
type: 'Circle',
|
type: 'Circle',
|
||||||
}),
|
}),
|
||||||
getActive: function () {
|
activeDraw: null,
|
||||||
return this.activeType ? this[this.activeType].getActive() : false;
|
|
||||||
},
|
|
||||||
setActive: function (active) {
|
setActive: function (active) {
|
||||||
const type = optionsForm.elements['draw-type'].value;
|
if (this.activeDraw) {
|
||||||
|
this.activeDraw.setActive(false);
|
||||||
|
this.activeDraw = null;
|
||||||
|
}
|
||||||
if (active) {
|
if (active) {
|
||||||
this.activeType && this[this.activeType].setActive(false);
|
const type = optionsForm.elements['draw-type'].value;
|
||||||
this[type].setActive(true);
|
this.activeDraw = this[type];
|
||||||
this.activeType = type;
|
this.activeDraw.setActive(true);
|
||||||
} else {
|
|
||||||
this.activeType && this[this.activeType].setActive(false);
|
|
||||||
this.activeType = null;
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
@@ -117,14 +115,16 @@ ExampleDraw.init();
|
|||||||
*/
|
*/
|
||||||
optionsForm.onchange = function (e) {
|
optionsForm.onchange = function (e) {
|
||||||
const type = e.target.getAttribute('name');
|
const type = e.target.getAttribute('name');
|
||||||
const value = e.target.value;
|
|
||||||
if (type == 'draw-type') {
|
if (type == 'draw-type') {
|
||||||
ExampleDraw.getActive() && ExampleDraw.setActive(true);
|
ExampleModify.setActive(false);
|
||||||
|
ExampleDraw.setActive(true);
|
||||||
|
optionsForm.elements['interaction'].value = 'draw';
|
||||||
} else if (type == 'interaction') {
|
} else if (type == 'interaction') {
|
||||||
if (value == 'modify') {
|
const interactionType = e.target.value;
|
||||||
|
if (interactionType == 'modify') {
|
||||||
ExampleDraw.setActive(false);
|
ExampleDraw.setActive(false);
|
||||||
ExampleModify.setActive(true);
|
ExampleModify.setActive(true);
|
||||||
} else if (value == 'draw') {
|
} else if (interactionType == 'draw') {
|
||||||
ExampleDraw.setActive(true);
|
ExampleDraw.setActive(true);
|
||||||
ExampleModify.setActive(false);
|
ExampleModify.setActive(false);
|
||||||
}
|
}
|
||||||
|
|||||||
+55
-73
@@ -181,18 +181,18 @@ class Snap extends PointerInteraction {
|
|||||||
/**
|
/**
|
||||||
* @const
|
* @const
|
||||||
* @private
|
* @private
|
||||||
* @type {Object<string, function(import("../Feature.js").default, import("../geom/Geometry.js").default): void>}
|
* @type {Object<string, function(Array<Array<import('../coordinate.js').Coordinate>>, import("../geom/Geometry.js").default): void>}
|
||||||
*/
|
*/
|
||||||
this.SEGMENT_WRITERS_ = {
|
this.GEOMETRY_SEGMENTERS_ = {
|
||||||
'Point': this.writePointGeometry_.bind(this),
|
'Point': this.segmentPointGemetry_.bind(this),
|
||||||
'LineString': this.writeLineStringGeometry_.bind(this),
|
'LineString': this.segmentLineStringGemetry_.bind(this),
|
||||||
'LinearRing': this.writeLineStringGeometry_.bind(this),
|
'LinearRing': this.segmentLineStringGemetry_.bind(this),
|
||||||
'Polygon': this.writePolygonGeometry_.bind(this),
|
'Polygon': this.segmentPolygonGemetry_.bind(this),
|
||||||
'MultiPoint': this.writeMultiPointGeometry_.bind(this),
|
'MultiPoint': this.segmentMultiPointGemetry_.bind(this),
|
||||||
'MultiLineString': this.writeMultiLineStringGeometry_.bind(this),
|
'MultiLineString': this.segmentMultiLineStringGemetry_.bind(this),
|
||||||
'MultiPolygon': this.writeMultiPolygonGeometry_.bind(this),
|
'MultiPolygon': this.segmentMultiPolygonGemetry_.bind(this),
|
||||||
'GeometryCollection': this.writeGeometryCollectionGeometry_.bind(this),
|
'GeometryCollection': this.segmentGeometryCollectionGemetry_.bind(this),
|
||||||
'Circle': this.writeCircleGeometry_.bind(this),
|
'Circle': this.segmentCircleGemetry_.bind(this),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -208,12 +208,27 @@ class Snap extends PointerInteraction {
|
|||||||
const feature_uid = getUid(feature);
|
const feature_uid = getUid(feature);
|
||||||
const geometry = feature.getGeometry();
|
const geometry = feature.getGeometry();
|
||||||
if (geometry) {
|
if (geometry) {
|
||||||
const segmentWriter = this.SEGMENT_WRITERS_[geometry.getType()];
|
const segmenter = this.GEOMETRY_SEGMENTERS_[geometry.getType()];
|
||||||
if (segmentWriter) {
|
if (segmenter) {
|
||||||
this.indexedFeaturesExtents_[feature_uid] = geometry.getExtent(
|
this.indexedFeaturesExtents_[feature_uid] = geometry.getExtent(
|
||||||
createEmpty()
|
createEmpty()
|
||||||
);
|
);
|
||||||
segmentWriter(feature, geometry);
|
const segments =
|
||||||
|
/** @type {Array<Array<import('../coordinate.js').Coordinate>>} */ ([]);
|
||||||
|
segmenter(segments, geometry);
|
||||||
|
if (segments.length === 1) {
|
||||||
|
this.rBush_.insert(boundingExtent(segments[0]), {
|
||||||
|
feature: feature,
|
||||||
|
segment: segments[0],
|
||||||
|
});
|
||||||
|
} else if (segments.length > 1) {
|
||||||
|
const extents = segments.map((s) => boundingExtent(s));
|
||||||
|
const segmentsData = segments.map((segment) => ({
|
||||||
|
feature: feature,
|
||||||
|
segment: segment,
|
||||||
|
}));
|
||||||
|
this.rBush_.load(extents, segmentsData);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -534,11 +549,11 @@ class Snap extends PointerInteraction {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {import("../Feature.js").default} feature Feature
|
* @param {Array<Array<import('../coordinate.js').Coordinate>>} segments Segments
|
||||||
* @param {import("../geom/Circle.js").default} geometry Geometry.
|
* @param {import("../geom/Circle.js").default} geometry Geometry.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
writeCircleGeometry_(feature, geometry) {
|
segmentCircleGemetry_(segments, geometry) {
|
||||||
const projection = this.getMap().getView().getProjection();
|
const projection = this.getMap().getView().getProjection();
|
||||||
let circleGeometry = geometry;
|
let circleGeometry = geometry;
|
||||||
const userProjection = getUserProjection();
|
const userProjection = getUserProjection();
|
||||||
@@ -553,134 +568,101 @@ class Snap extends PointerInteraction {
|
|||||||
}
|
}
|
||||||
const coordinates = polygon.getCoordinates()[0];
|
const coordinates = polygon.getCoordinates()[0];
|
||||||
for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) {
|
for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) {
|
||||||
const segment = coordinates.slice(i, i + 2);
|
segments.push(coordinates.slice(i, i + 2));
|
||||||
const segmentData = {
|
|
||||||
feature: feature,
|
|
||||||
segment: segment,
|
|
||||||
};
|
|
||||||
this.rBush_.insert(boundingExtent(segment), segmentData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {import("../Feature.js").default} feature Feature
|
* @param {Array<Array<import('../coordinate.js').Coordinate>>} segments Segments
|
||||||
* @param {import("../geom/GeometryCollection.js").default} geometry Geometry.
|
* @param {import("../geom/GeometryCollection.js").default} geometry Geometry.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
writeGeometryCollectionGeometry_(feature, geometry) {
|
segmentGeometryCollectionGemetry_(segments, geometry) {
|
||||||
const geometries = geometry.getGeometriesArray();
|
const geometries = geometry.getGeometriesArray();
|
||||||
for (let i = 0; i < geometries.length; ++i) {
|
for (let i = 0; i < geometries.length; ++i) {
|
||||||
const segmentWriter = this.SEGMENT_WRITERS_[geometries[i].getType()];
|
const segmenter = this.GEOMETRY_SEGMENTERS_[geometries[i].getType()];
|
||||||
if (segmentWriter) {
|
if (segmenter) {
|
||||||
segmentWriter(feature, geometries[i]);
|
segmenter(segments, geometries[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {import("../Feature.js").default} feature Feature
|
* @param {Array<Array<import('../coordinate.js').Coordinate>>} segments Segments
|
||||||
* @param {import("../geom/LineString.js").default} geometry Geometry.
|
* @param {import("../geom/LineString.js").default} geometry Geometry.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
writeLineStringGeometry_(feature, geometry) {
|
segmentLineStringGemetry_(segments, geometry) {
|
||||||
const coordinates = geometry.getCoordinates();
|
const coordinates = geometry.getCoordinates();
|
||||||
for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) {
|
for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) {
|
||||||
const segment = coordinates.slice(i, i + 2);
|
segments.push(coordinates.slice(i, i + 2));
|
||||||
const segmentData = {
|
|
||||||
feature: feature,
|
|
||||||
segment: segment,
|
|
||||||
};
|
|
||||||
this.rBush_.insert(boundingExtent(segment), segmentData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {import("../Feature.js").default} feature Feature
|
* @param {Array<Array<import('../coordinate.js').Coordinate>>} segments Segments
|
||||||
* @param {import("../geom/MultiLineString.js").default} geometry Geometry.
|
* @param {import("../geom/MultiLineString.js").default} geometry Geometry.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
writeMultiLineStringGeometry_(feature, geometry) {
|
segmentMultiLineStringGemetry_(segments, geometry) {
|
||||||
const lines = geometry.getCoordinates();
|
const lines = geometry.getCoordinates();
|
||||||
for (let j = 0, jj = lines.length; j < jj; ++j) {
|
for (let j = 0, jj = lines.length; j < jj; ++j) {
|
||||||
const coordinates = lines[j];
|
const coordinates = lines[j];
|
||||||
for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) {
|
for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) {
|
||||||
const segment = coordinates.slice(i, i + 2);
|
segments.push(coordinates.slice(i, i + 2));
|
||||||
const segmentData = {
|
|
||||||
feature: feature,
|
|
||||||
segment: segment,
|
|
||||||
};
|
|
||||||
this.rBush_.insert(boundingExtent(segment), segmentData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {import("../Feature.js").default} feature Feature
|
* @param {Array<Array<import('../coordinate.js').Coordinate>>} segments Segments
|
||||||
* @param {import("../geom/MultiPoint.js").default} geometry Geometry.
|
* @param {import("../geom/MultiPoint.js").default} geometry Geometry.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
writeMultiPointGeometry_(feature, geometry) {
|
segmentMultiPointGemetry_(segments, geometry) {
|
||||||
geometry.getCoordinates().forEach((point) => {
|
geometry.getCoordinates().forEach((point) => {
|
||||||
const segmentData = {
|
segments.push([point]);
|
||||||
feature: feature,
|
|
||||||
segment: [point],
|
|
||||||
};
|
|
||||||
this.rBush_.insert(geometry.getExtent(), segmentData);
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {import("../Feature.js").default} feature Feature
|
* @param {Array<Array<import('../coordinate.js').Coordinate>>} segments Segments
|
||||||
* @param {import("../geom/MultiPolygon.js").default} geometry Geometry.
|
* @param {import("../geom/MultiPolygon.js").default} geometry Geometry.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
writeMultiPolygonGeometry_(feature, geometry) {
|
segmentMultiPolygonGemetry_(segments, geometry) {
|
||||||
const polygons = geometry.getCoordinates();
|
const polygons = geometry.getCoordinates();
|
||||||
for (let k = 0, kk = polygons.length; k < kk; ++k) {
|
for (let k = 0, kk = polygons.length; k < kk; ++k) {
|
||||||
const rings = polygons[k];
|
const rings = polygons[k];
|
||||||
for (let j = 0, jj = rings.length; j < jj; ++j) {
|
for (let j = 0, jj = rings.length; j < jj; ++j) {
|
||||||
const coordinates = rings[j];
|
const coordinates = rings[j];
|
||||||
for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) {
|
for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) {
|
||||||
const segment = coordinates.slice(i, i + 2);
|
segments.push(coordinates.slice(i, i + 2));
|
||||||
const segmentData = {
|
|
||||||
feature: feature,
|
|
||||||
segment: segment,
|
|
||||||
};
|
|
||||||
this.rBush_.insert(boundingExtent(segment), segmentData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {import("../Feature.js").default} feature Feature
|
* @param {Array<Array<import('../coordinate.js').Coordinate>>} segments Segments
|
||||||
* @param {import("../geom/Point.js").default} geometry Geometry.
|
* @param {import("../geom/Point.js").default} geometry Geometry.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
writePointGeometry_(feature, geometry) {
|
segmentPointGemetry_(segments, geometry) {
|
||||||
const segmentData = {
|
segments.push([geometry.getCoordinates()]);
|
||||||
feature: feature,
|
|
||||||
segment: [geometry.getCoordinates()],
|
|
||||||
};
|
|
||||||
this.rBush_.insert(geometry.getExtent(), segmentData);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {import("../Feature.js").default} feature Feature
|
* @param {Array<Array<import('../coordinate.js').Coordinate>>} segments Segments
|
||||||
* @param {import("../geom/Polygon.js").default} geometry Geometry.
|
* @param {import("../geom/Polygon.js").default} geometry Geometry.
|
||||||
* @private
|
* @private
|
||||||
*/
|
*/
|
||||||
writePolygonGeometry_(feature, geometry) {
|
segmentPolygonGemetry_(segments, geometry) {
|
||||||
const rings = geometry.getCoordinates();
|
const rings = geometry.getCoordinates();
|
||||||
for (let j = 0, jj = rings.length; j < jj; ++j) {
|
for (let j = 0, jj = rings.length; j < jj; ++j) {
|
||||||
const coordinates = rings[j];
|
const coordinates = rings[j];
|
||||||
for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) {
|
for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) {
|
||||||
const segment = coordinates.slice(i, i + 2);
|
segments.push(coordinates.slice(i, i + 2));
|
||||||
const segmentData = {
|
|
||||||
feature: feature,
|
|
||||||
segment: segment,
|
|
||||||
};
|
|
||||||
this.rBush_.insert(boundingExtent(segment), segmentData);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user