Compare commits
52 Commits
v6.13.0
...
dependabot
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
745d0cc5cc | ||
|
|
2ccd95dfbd | ||
|
|
07761e96a3 | ||
|
|
182fbdeb07 | ||
|
|
f3208a2331 | ||
|
|
373cf81fc0 | ||
|
|
6f8f2cd666 | ||
|
|
5c7b9124cc | ||
|
|
46ddbd7e0e | ||
|
|
7d9cf83efe | ||
|
|
2d63e29e04 | ||
|
|
05d7cd62b7 | ||
|
|
3b637a7939 | ||
|
|
bcebd73388 | ||
|
|
444763f47b | ||
|
|
b50b9bd887 | ||
|
|
f064a19717 | ||
|
|
f7b5b314cb | ||
|
|
b85c6d17e8 | ||
|
|
dcdc445c5d | ||
|
|
b1e92ba97e | ||
|
|
c638709c18 | ||
|
|
9c74ee85e5 | ||
|
|
c7634aa00e | ||
|
|
7f93140711 | ||
|
|
6067048495 | ||
|
|
49acb39f72 | ||
|
|
e47bd0bb93 | ||
|
|
8b5b5db00f | ||
|
|
e42555af6e | ||
|
|
1ae1ff26a0 | ||
|
|
5c1729932d | ||
|
|
87d87a155a | ||
|
|
0c23e17e13 | ||
|
|
7a78f11f3f | ||
|
|
9850839229 | ||
|
|
8615d352c7 | ||
|
|
db20d33557 | ||
|
|
75b5f60c76 | ||
|
|
d38f08b41c | ||
|
|
17033e162d | ||
|
|
4eb2acfbbb | ||
|
|
c5edb50557 | ||
|
|
28b6026bc4 | ||
|
|
e31f241b99 | ||
|
|
d92953d242 | ||
|
|
2f371d11c0 | ||
|
|
c3a8890de5 | ||
|
|
184b658a2e | ||
|
|
20e352111c | ||
|
|
b5a30f945c | ||
|
|
bb7b52e468 |
@@ -48,7 +48,7 @@ export default {
|
||||
},
|
||||
output: {
|
||||
path: path.resolve('./build/legacy'),
|
||||
publicPath: '',
|
||||
publicPath: 'auto',
|
||||
filename: 'ol.js',
|
||||
library: 'ol',
|
||||
libraryTarget: 'umd',
|
||||
|
||||
@@ -16,15 +16,6 @@ tags: "draw, edit, modify, vector, snap"
|
||||
<input type="radio" name="interaction" value="draw" id="draw" checked>
|
||||
Draw
|
||||
</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">
|
||||
<option value="Point">Point</option>
|
||||
<option value="LineString">LineString</option>
|
||||
@@ -32,4 +23,10 @@ tags: "draw, edit, modify, vector, snap"
|
||||
<option value="Circle">Circle</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="radio">
|
||||
<label>
|
||||
<input type="radio" name="interaction" value="modify">
|
||||
Modify
|
||||
</label>
|
||||
</div>
|
||||
</form>
|
||||
|
||||
@@ -94,18 +94,16 @@ const ExampleDraw = {
|
||||
source: vector.getSource(),
|
||||
type: 'Circle',
|
||||
}),
|
||||
getActive: function () {
|
||||
return this.activeType ? this[this.activeType].getActive() : false;
|
||||
},
|
||||
activeDraw: null,
|
||||
setActive: function (active) {
|
||||
const type = optionsForm.elements['draw-type'].value;
|
||||
if (this.activeDraw) {
|
||||
this.activeDraw.setActive(false);
|
||||
this.activeDraw = null;
|
||||
}
|
||||
if (active) {
|
||||
this.activeType && this[this.activeType].setActive(false);
|
||||
this[type].setActive(true);
|
||||
this.activeType = type;
|
||||
} else {
|
||||
this.activeType && this[this.activeType].setActive(false);
|
||||
this.activeType = null;
|
||||
const type = optionsForm.elements['draw-type'].value;
|
||||
this.activeDraw = this[type];
|
||||
this.activeDraw.setActive(true);
|
||||
}
|
||||
},
|
||||
};
|
||||
@@ -117,14 +115,16 @@ ExampleDraw.init();
|
||||
*/
|
||||
optionsForm.onchange = function (e) {
|
||||
const type = e.target.getAttribute('name');
|
||||
const value = e.target.value;
|
||||
if (type == 'draw-type') {
|
||||
ExampleDraw.getActive() && ExampleDraw.setActive(true);
|
||||
ExampleModify.setActive(false);
|
||||
ExampleDraw.setActive(true);
|
||||
optionsForm.elements['interaction'].value = 'draw';
|
||||
} else if (type == 'interaction') {
|
||||
if (value == 'modify') {
|
||||
const interactionType = e.target.value;
|
||||
if (interactionType == 'modify') {
|
||||
ExampleDraw.setActive(false);
|
||||
ExampleModify.setActive(true);
|
||||
} else if (value == 'draw') {
|
||||
} else if (interactionType == 'draw') {
|
||||
ExampleDraw.setActive(true);
|
||||
ExampleModify.setActive(false);
|
||||
}
|
||||
|
||||
1172
package-lock.json
generated
1172
package-lock.json
generated
File diff suppressed because it is too large
Load Diff
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "ol",
|
||||
"version": "6.13.0",
|
||||
"version": "6.13.1-dev",
|
||||
"description": "OpenLayers mapping library",
|
||||
"keywords": [
|
||||
"map",
|
||||
@@ -91,7 +91,7 @@
|
||||
"pixelmatch": "^5.1.0",
|
||||
"pngjs": "^6.0.0",
|
||||
"proj4": "^2.7.5",
|
||||
"puppeteer": "13.3.2",
|
||||
"puppeteer": "13.4.1",
|
||||
"regenerator-runtime": "^0.13.9",
|
||||
"rollup": "^2.42.3",
|
||||
"rollup-plugin-terser": "^7.0.2",
|
||||
@@ -99,7 +99,7 @@
|
||||
"shx": "^0.3.2",
|
||||
"sinon": "^13.0.0",
|
||||
"threads": "^1.6.5",
|
||||
"typescript": "4.6.0-beta",
|
||||
"typescript": "4.6.2",
|
||||
"walk": "^2.3.9",
|
||||
"webpack": "^5.27.2",
|
||||
"webpack-cli": "^4.5.0",
|
||||
|
||||
@@ -391,7 +391,7 @@ class PluggableMap extends BaseObject {
|
||||
this.overlayIdIndex_ = {};
|
||||
|
||||
/**
|
||||
* @type {import("./renderer/Map.js").default}
|
||||
* @type {import("./renderer/Map.js").default|null}
|
||||
* @private
|
||||
*/
|
||||
this.renderer_ = null;
|
||||
@@ -622,7 +622,7 @@ class PluggableMap extends BaseObject {
|
||||
* @api
|
||||
*/
|
||||
forEachFeatureAtPixel(pixel, callback, opt_options) {
|
||||
if (!this.frameState_) {
|
||||
if (!this.frameState_ || !this.renderer_) {
|
||||
return;
|
||||
}
|
||||
const coordinate = this.getCoordinateFromPixelInternal(pixel);
|
||||
@@ -713,7 +713,7 @@ class PluggableMap extends BaseObject {
|
||||
* @deprecated
|
||||
*/
|
||||
forEachLayerAtPixel(pixel, callback, opt_options) {
|
||||
if (!this.frameState_) {
|
||||
if (!this.frameState_ || !this.renderer_) {
|
||||
return;
|
||||
}
|
||||
const options = opt_options || {};
|
||||
@@ -738,7 +738,7 @@ class PluggableMap extends BaseObject {
|
||||
* @api
|
||||
*/
|
||||
hasFeatureAtPixel(pixel, opt_options) {
|
||||
if (!this.frameState_) {
|
||||
if (!this.frameState_ || !this.renderer_) {
|
||||
return false;
|
||||
}
|
||||
const coordinate = this.getCoordinateFromPixelInternal(pixel);
|
||||
@@ -950,12 +950,16 @@ class PluggableMap extends BaseObject {
|
||||
getLoadingOrNotReady() {
|
||||
const layerStatesArray = this.getLayerGroup().getLayerStatesArray();
|
||||
for (let i = 0, ii = layerStatesArray.length; i < ii; ++i) {
|
||||
const layer = layerStatesArray[i].layer;
|
||||
if (!layer.getRenderer().ready) {
|
||||
const state = layerStatesArray[i];
|
||||
if (!state.visible) {
|
||||
continue;
|
||||
}
|
||||
const renderer = state.layer.getRenderer();
|
||||
if (renderer && !renderer.ready) {
|
||||
return true;
|
||||
}
|
||||
const source = /** @type {import("./layer/Layer.js").default} */ (
|
||||
layer
|
||||
state.layer
|
||||
).getSource();
|
||||
if (source && source.loading) {
|
||||
return true;
|
||||
@@ -999,7 +1003,7 @@ class PluggableMap extends BaseObject {
|
||||
|
||||
/**
|
||||
* Get the map renderer.
|
||||
* @return {import("./renderer/Map.js").default} Renderer
|
||||
* @return {import("./renderer/Map.js").default|null} Renderer
|
||||
*/
|
||||
getRenderer() {
|
||||
return this.renderer_;
|
||||
@@ -1185,6 +1189,7 @@ class PluggableMap extends BaseObject {
|
||||
|
||||
if (
|
||||
frameState &&
|
||||
this.renderer_ &&
|
||||
this.hasListener(RenderEventType.RENDERCOMPLETE) &&
|
||||
!frameState.animate &&
|
||||
this.renderComplete_
|
||||
@@ -1525,7 +1530,9 @@ class PluggableMap extends BaseObject {
|
||||
}
|
||||
|
||||
this.frameState_ = frameState;
|
||||
this.renderer_.renderFrame(frameState);
|
||||
/** @type {import("./renderer/Map.js").default} */ (
|
||||
this.renderer_
|
||||
).renderFrame(frameState);
|
||||
|
||||
if (frameState) {
|
||||
if (frameState.animate) {
|
||||
|
||||
@@ -401,15 +401,15 @@ class View extends BaseObject {
|
||||
*/
|
||||
this.cancelAnchor_ = undefined;
|
||||
|
||||
if (options.projection) {
|
||||
disableCoordinateWarning();
|
||||
}
|
||||
if (options.center) {
|
||||
options.center = fromUserCoordinate(options.center, this.projection_);
|
||||
}
|
||||
if (options.extent) {
|
||||
options.extent = fromUserExtent(options.extent, this.projection_);
|
||||
}
|
||||
if (options.projection) {
|
||||
disableCoordinateWarning();
|
||||
}
|
||||
|
||||
this.applyOptions_(options);
|
||||
}
|
||||
|
||||
@@ -105,6 +105,29 @@ class FullScreen extends Control {
|
||||
*/
|
||||
this.un;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.keys_ = options.keys !== undefined ? options.keys : false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLElement|string|undefined}
|
||||
*/
|
||||
this.source_ = options.source;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.isInFullscreen_ = false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
this.boundHandleMapTargetChange_ = this.handleMapTargetChange_.bind(this);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {string}
|
||||
@@ -157,48 +180,25 @@ class FullScreen extends Control {
|
||||
? document.createTextNode(labelActive)
|
||||
: labelActive;
|
||||
|
||||
const tipLabel = options.tipLabel ? options.tipLabel : 'Toggle full-screen';
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLElement}
|
||||
*/
|
||||
this.button_ = document.createElement('button');
|
||||
|
||||
const tipLabel = options.tipLabel ? options.tipLabel : 'Toggle full-screen';
|
||||
this.button_.setAttribute('type', 'button');
|
||||
this.button_.title = tipLabel;
|
||||
this.button_.setAttribute('type', 'button');
|
||||
this.button_.appendChild(this.labelNode_);
|
||||
|
||||
this.button_.addEventListener(
|
||||
EventType.CLICK,
|
||||
this.handleClick_.bind(this),
|
||||
false
|
||||
);
|
||||
this.setClassName_(this.button_, this.isInFullscreen_);
|
||||
|
||||
this.element.className = `${this.cssClassName_} ${CLASS_UNSELECTABLE} ${CLASS_CONTROL}`;
|
||||
this.element.appendChild(this.button_);
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {boolean}
|
||||
*/
|
||||
this.keys_ = options.keys !== undefined ? options.keys : false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {HTMLElement|string|undefined}
|
||||
*/
|
||||
this.source_ = options.source;
|
||||
|
||||
/**
|
||||
* @type {boolean}
|
||||
* @private
|
||||
*/
|
||||
this.isInFullscreen_ = false;
|
||||
|
||||
/**
|
||||
* @private
|
||||
*/
|
||||
this.boundHandleMapTargetChange_ = this.handleMapTargetChange_.bind(this);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -271,12 +271,13 @@ class FullScreen extends Control {
|
||||
* @private
|
||||
*/
|
||||
setClassName_(element, fullscreen) {
|
||||
const activeClassName = this.activeClassName_;
|
||||
const inactiveClassName = this.inactiveClassName_;
|
||||
const nextClassName = fullscreen ? activeClassName : inactiveClassName;
|
||||
element.classList.remove(...activeClassName);
|
||||
element.classList.remove(...inactiveClassName);
|
||||
element.classList.add(...nextClassName);
|
||||
if (fullscreen) {
|
||||
element.classList.remove(...this.inactiveClassName_);
|
||||
element.classList.add(...this.activeClassName_);
|
||||
} else {
|
||||
element.classList.remove(...this.activeClassName_);
|
||||
element.classList.add(...this.inactiveClassName_);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -12,9 +12,7 @@ import {boundingExtent, createEmpty} from '../extent.js';
|
||||
import {
|
||||
closestOnCircle,
|
||||
closestOnSegment,
|
||||
distance as coordinateDistance,
|
||||
squaredDistance as squaredCoordinateDistance,
|
||||
squaredDistanceToSegment,
|
||||
squaredDistance,
|
||||
} from '../coordinate.js';
|
||||
import {fromCircle} from '../geom/Polygon.js';
|
||||
import {
|
||||
@@ -28,7 +26,6 @@ import {listen, unlistenByKey} from '../events.js';
|
||||
|
||||
/**
|
||||
* @typedef {Object} Result
|
||||
* @property {boolean} snapped Snapped.
|
||||
* @property {import("../coordinate.js").Coordinate|null} vertex Vertex.
|
||||
* @property {import("../pixel.js").Pixel|null} vertexPixel VertexPixel.
|
||||
*/
|
||||
@@ -184,18 +181,18 @@ class Snap extends PointerInteraction {
|
||||
/**
|
||||
* @const
|
||||
* @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_ = {
|
||||
'Point': this.writePointGeometry_.bind(this),
|
||||
'LineString': this.writeLineStringGeometry_.bind(this),
|
||||
'LinearRing': this.writeLineStringGeometry_.bind(this),
|
||||
'Polygon': this.writePolygonGeometry_.bind(this),
|
||||
'MultiPoint': this.writeMultiPointGeometry_.bind(this),
|
||||
'MultiLineString': this.writeMultiLineStringGeometry_.bind(this),
|
||||
'MultiPolygon': this.writeMultiPolygonGeometry_.bind(this),
|
||||
'GeometryCollection': this.writeGeometryCollectionGeometry_.bind(this),
|
||||
'Circle': this.writeCircleGeometry_.bind(this),
|
||||
this.GEOMETRY_SEGMENTERS_ = {
|
||||
'Point': this.segmentPointGemetry_.bind(this),
|
||||
'LineString': this.segmentLineStringGemetry_.bind(this),
|
||||
'LinearRing': this.segmentLineStringGemetry_.bind(this),
|
||||
'Polygon': this.segmentPolygonGemetry_.bind(this),
|
||||
'MultiPoint': this.segmentMultiPointGemetry_.bind(this),
|
||||
'MultiLineString': this.segmentMultiLineStringGemetry_.bind(this),
|
||||
'MultiPolygon': this.segmentMultiPolygonGemetry_.bind(this),
|
||||
'GeometryCollection': this.segmentGeometryCollectionGemetry_.bind(this),
|
||||
'Circle': this.segmentCircleGemetry_.bind(this),
|
||||
};
|
||||
}
|
||||
|
||||
@@ -211,12 +208,27 @@ class Snap extends PointerInteraction {
|
||||
const feature_uid = getUid(feature);
|
||||
const geometry = feature.getGeometry();
|
||||
if (geometry) {
|
||||
const segmentWriter = this.SEGMENT_WRITERS_[geometry.getType()];
|
||||
if (segmentWriter) {
|
||||
const segmenter = this.GEOMETRY_SEGMENTERS_[geometry.getType()];
|
||||
if (segmenter) {
|
||||
this.indexedFeaturesExtents_[feature_uid] = geometry.getExtent(
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -266,7 +278,7 @@ class Snap extends PointerInteraction {
|
||||
*/
|
||||
handleEvent(evt) {
|
||||
const result = this.snapTo(evt.pixel, evt.coordinate, evt.map);
|
||||
if (result.snapped) {
|
||||
if (result) {
|
||||
evt.coordinate = result.vertex.slice(0, 2);
|
||||
evt.pixel = result.vertexPixel;
|
||||
}
|
||||
@@ -411,7 +423,7 @@ class Snap extends PointerInteraction {
|
||||
* @param {import("../pixel.js").Pixel} pixel Pixel
|
||||
* @param {import("../coordinate.js").Coordinate} pixelCoordinate Coordinate
|
||||
* @param {import("../PluggableMap.js").default} map Map.
|
||||
* @return {Result} Snap result
|
||||
* @return {Result|null} Snap result
|
||||
*/
|
||||
snapTo(pixel, pixelCoordinate, map) {
|
||||
const lowerLeft = map.getCoordinateFromPixel([
|
||||
@@ -424,113 +436,107 @@ class Snap extends PointerInteraction {
|
||||
]);
|
||||
const box = boundingExtent([lowerLeft, upperRight]);
|
||||
|
||||
let segments = this.rBush_.getInExtent(box);
|
||||
const segments = this.rBush_.getInExtent(box);
|
||||
|
||||
// If snapping on vertices only, don't consider circles
|
||||
if (this.vertex_ && !this.edge_) {
|
||||
segments = segments.filter(function (segment) {
|
||||
return segment.feature.getGeometry().getType() !== GeometryType.CIRCLE;
|
||||
});
|
||||
}
|
||||
|
||||
let snapped = false;
|
||||
let vertex = null;
|
||||
let vertexPixel = null;
|
||||
|
||||
if (segments.length === 0) {
|
||||
return {
|
||||
snapped: snapped,
|
||||
vertex: vertex,
|
||||
vertexPixel: vertexPixel,
|
||||
};
|
||||
const segmentsLength = segments.length;
|
||||
if (segmentsLength === 0) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const projection = map.getView().getProjection();
|
||||
const projectedCoordinate = fromUserCoordinate(pixelCoordinate, projection);
|
||||
|
||||
let closestSegmentData;
|
||||
let closestVertex;
|
||||
let minSquaredDistance = Infinity;
|
||||
for (let i = 0; i < segments.length; ++i) {
|
||||
const segmentData = segments[i];
|
||||
tempSegment[0] = fromUserCoordinate(segmentData.segment[0], projection);
|
||||
tempSegment[1] = fromUserCoordinate(segmentData.segment[1], projection);
|
||||
const delta = squaredDistanceToSegment(projectedCoordinate, tempSegment);
|
||||
if (delta < minSquaredDistance) {
|
||||
closestSegmentData = segmentData;
|
||||
minSquaredDistance = delta;
|
||||
|
||||
const squaredPixelTolerance = this.pixelTolerance_ * this.pixelTolerance_;
|
||||
const getResult = () => {
|
||||
if (closestVertex) {
|
||||
const vertexPixel = map.getPixelFromCoordinate(closestVertex);
|
||||
const squaredPixelDistance = squaredDistance(pixel, vertexPixel);
|
||||
if (squaredPixelDistance <= squaredPixelTolerance) {
|
||||
return {
|
||||
vertex: closestVertex,
|
||||
vertexPixel: [
|
||||
Math.round(vertexPixel[0]),
|
||||
Math.round(vertexPixel[1]),
|
||||
],
|
||||
};
|
||||
}
|
||||
}
|
||||
return null;
|
||||
};
|
||||
|
||||
if (this.vertex_) {
|
||||
for (let i = 0; i < segmentsLength; ++i) {
|
||||
const segmentData = segments[i];
|
||||
if (
|
||||
segmentData.feature.getGeometry().getType() !== GeometryType.CIRCLE
|
||||
) {
|
||||
segmentData.segment.forEach((vertex) => {
|
||||
const tempVertexCoord = fromUserCoordinate(vertex, projection);
|
||||
const delta = squaredDistance(projectedCoordinate, tempVertexCoord);
|
||||
if (delta < minSquaredDistance) {
|
||||
closestVertex = vertex;
|
||||
minSquaredDistance = delta;
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
const result = getResult();
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
const closestSegment = closestSegmentData.segment;
|
||||
|
||||
if (this.vertex_ && !this.edge_) {
|
||||
const pixel1 = map.getPixelFromCoordinate(closestSegment[0]);
|
||||
const pixel2 = map.getPixelFromCoordinate(closestSegment[1]);
|
||||
const squaredDist1 = squaredCoordinateDistance(pixel, pixel1);
|
||||
const squaredDist2 = squaredCoordinateDistance(pixel, pixel2);
|
||||
const dist = Math.sqrt(Math.min(squaredDist1, squaredDist2));
|
||||
if (dist <= this.pixelTolerance_) {
|
||||
snapped = true;
|
||||
vertex =
|
||||
squaredDist1 > squaredDist2 ? closestSegment[1] : closestSegment[0];
|
||||
vertexPixel = map.getPixelFromCoordinate(vertex);
|
||||
}
|
||||
} else if (this.edge_) {
|
||||
const isCircle =
|
||||
closestSegmentData.feature.getGeometry().getType() ===
|
||||
GeometryType.CIRCLE;
|
||||
if (isCircle) {
|
||||
let circleGeometry = closestSegmentData.feature.getGeometry();
|
||||
const userProjection = getUserProjection();
|
||||
if (userProjection) {
|
||||
circleGeometry = circleGeometry
|
||||
.clone()
|
||||
.transform(userProjection, projection);
|
||||
if (this.edge_) {
|
||||
for (let i = 0; i < segmentsLength; ++i) {
|
||||
let vertex = null;
|
||||
const segmentData = segments[i];
|
||||
if (
|
||||
segmentData.feature.getGeometry().getType() === GeometryType.CIRCLE
|
||||
) {
|
||||
let circleGeometry = segmentData.feature.getGeometry();
|
||||
const userProjection = getUserProjection();
|
||||
if (userProjection) {
|
||||
circleGeometry = circleGeometry
|
||||
.clone()
|
||||
.transform(userProjection, projection);
|
||||
}
|
||||
vertex = toUserCoordinate(
|
||||
closestOnCircle(
|
||||
projectedCoordinate,
|
||||
/** @type {import("../geom/Circle.js").default} */ (
|
||||
circleGeometry
|
||||
)
|
||||
),
|
||||
projection
|
||||
);
|
||||
} else {
|
||||
const [segmentStart, segmentEnd] = segmentData.segment;
|
||||
// points have only one coordinate
|
||||
if (segmentEnd) {
|
||||
tempSegment[0] = fromUserCoordinate(segmentStart, projection);
|
||||
tempSegment[1] = fromUserCoordinate(segmentEnd, projection);
|
||||
vertex = closestOnSegment(projectedCoordinate, tempSegment);
|
||||
}
|
||||
}
|
||||
vertex = toUserCoordinate(
|
||||
closestOnCircle(
|
||||
projectedCoordinate,
|
||||
/** @type {import("../geom/Circle.js").default} */ (circleGeometry)
|
||||
),
|
||||
projection
|
||||
);
|
||||
} else {
|
||||
tempSegment[0] = fromUserCoordinate(closestSegment[0], projection);
|
||||
tempSegment[1] = fromUserCoordinate(closestSegment[1], projection);
|
||||
vertex = toUserCoordinate(
|
||||
closestOnSegment(projectedCoordinate, tempSegment),
|
||||
projection
|
||||
);
|
||||
}
|
||||
vertexPixel = map.getPixelFromCoordinate(vertex);
|
||||
|
||||
if (coordinateDistance(pixel, vertexPixel) <= this.pixelTolerance_) {
|
||||
snapped = true;
|
||||
if (this.vertex_ && !isCircle) {
|
||||
const pixel1 = map.getPixelFromCoordinate(closestSegment[0]);
|
||||
const pixel2 = map.getPixelFromCoordinate(closestSegment[1]);
|
||||
const squaredDist1 = squaredCoordinateDistance(vertexPixel, pixel1);
|
||||
const squaredDist2 = squaredCoordinateDistance(vertexPixel, pixel2);
|
||||
const dist = Math.sqrt(Math.min(squaredDist1, squaredDist2));
|
||||
if (dist <= this.pixelTolerance_) {
|
||||
vertex =
|
||||
squaredDist1 > squaredDist2
|
||||
? closestSegment[1]
|
||||
: closestSegment[0];
|
||||
vertexPixel = map.getPixelFromCoordinate(vertex);
|
||||
if (vertex) {
|
||||
const delta = squaredDistance(projectedCoordinate, vertex);
|
||||
if (delta < minSquaredDistance) {
|
||||
closestVertex = vertex;
|
||||
minSquaredDistance = delta;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const result = getResult();
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (snapped) {
|
||||
vertexPixel = [Math.round(vertexPixel[0]), Math.round(vertexPixel[1])];
|
||||
}
|
||||
|
||||
return {
|
||||
snapped: snapped,
|
||||
vertex: vertex,
|
||||
vertexPixel: vertexPixel,
|
||||
};
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -543,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.
|
||||
* @private
|
||||
*/
|
||||
writeCircleGeometry_(feature, geometry) {
|
||||
segmentCircleGemetry_(segments, geometry) {
|
||||
const projection = this.getMap().getView().getProjection();
|
||||
let circleGeometry = geometry;
|
||||
const userProjection = getUserProjection();
|
||||
@@ -562,137 +568,101 @@ class Snap extends PointerInteraction {
|
||||
}
|
||||
const coordinates = polygon.getCoordinates()[0];
|
||||
for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) {
|
||||
const segment = coordinates.slice(i, i + 2);
|
||||
const segmentData = {
|
||||
feature: feature,
|
||||
segment: segment,
|
||||
};
|
||||
this.rBush_.insert(boundingExtent(segment), segmentData);
|
||||
segments.push(coordinates.slice(i, i + 2));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../Feature.js").default} feature Feature
|
||||
* @param {Array<Array<import('../coordinate.js').Coordinate>>} segments Segments
|
||||
* @param {import("../geom/GeometryCollection.js").default} geometry Geometry.
|
||||
* @private
|
||||
*/
|
||||
writeGeometryCollectionGeometry_(feature, geometry) {
|
||||
segmentGeometryCollectionGemetry_(segments, geometry) {
|
||||
const geometries = geometry.getGeometriesArray();
|
||||
for (let i = 0; i < geometries.length; ++i) {
|
||||
const segmentWriter = this.SEGMENT_WRITERS_[geometries[i].getType()];
|
||||
if (segmentWriter) {
|
||||
segmentWriter(feature, geometries[i]);
|
||||
const segmenter = this.GEOMETRY_SEGMENTERS_[geometries[i].getType()];
|
||||
if (segmenter) {
|
||||
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.
|
||||
* @private
|
||||
*/
|
||||
writeLineStringGeometry_(feature, geometry) {
|
||||
segmentLineStringGemetry_(segments, geometry) {
|
||||
const coordinates = geometry.getCoordinates();
|
||||
for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) {
|
||||
const segment = coordinates.slice(i, i + 2);
|
||||
const segmentData = {
|
||||
feature: feature,
|
||||
segment: segment,
|
||||
};
|
||||
this.rBush_.insert(boundingExtent(segment), segmentData);
|
||||
segments.push(coordinates.slice(i, i + 2));
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../Feature.js").default} feature Feature
|
||||
* @param {Array<Array<import('../coordinate.js').Coordinate>>} segments Segments
|
||||
* @param {import("../geom/MultiLineString.js").default} geometry Geometry.
|
||||
* @private
|
||||
*/
|
||||
writeMultiLineStringGeometry_(feature, geometry) {
|
||||
segmentMultiLineStringGemetry_(segments, geometry) {
|
||||
const lines = geometry.getCoordinates();
|
||||
for (let j = 0, jj = lines.length; j < jj; ++j) {
|
||||
const coordinates = lines[j];
|
||||
for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) {
|
||||
const segment = coordinates.slice(i, i + 2);
|
||||
const segmentData = {
|
||||
feature: feature,
|
||||
segment: segment,
|
||||
};
|
||||
this.rBush_.insert(boundingExtent(segment), segmentData);
|
||||
segments.push(coordinates.slice(i, i + 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../Feature.js").default} feature Feature
|
||||
* @param {Array<Array<import('../coordinate.js').Coordinate>>} segments Segments
|
||||
* @param {import("../geom/MultiPoint.js").default} geometry Geometry.
|
||||
* @private
|
||||
*/
|
||||
writeMultiPointGeometry_(feature, geometry) {
|
||||
const points = geometry.getCoordinates();
|
||||
for (let i = 0, ii = points.length; i < ii; ++i) {
|
||||
const coordinates = points[i];
|
||||
const segmentData = {
|
||||
feature: feature,
|
||||
segment: [coordinates, coordinates],
|
||||
};
|
||||
this.rBush_.insert(geometry.getExtent(), segmentData);
|
||||
}
|
||||
segmentMultiPointGemetry_(segments, geometry) {
|
||||
geometry.getCoordinates().forEach((point) => {
|
||||
segments.push([point]);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../Feature.js").default} feature Feature
|
||||
* @param {Array<Array<import('../coordinate.js').Coordinate>>} segments Segments
|
||||
* @param {import("../geom/MultiPolygon.js").default} geometry Geometry.
|
||||
* @private
|
||||
*/
|
||||
writeMultiPolygonGeometry_(feature, geometry) {
|
||||
segmentMultiPolygonGemetry_(segments, geometry) {
|
||||
const polygons = geometry.getCoordinates();
|
||||
for (let k = 0, kk = polygons.length; k < kk; ++k) {
|
||||
const rings = polygons[k];
|
||||
for (let j = 0, jj = rings.length; j < jj; ++j) {
|
||||
const coordinates = rings[j];
|
||||
for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) {
|
||||
const segment = coordinates.slice(i, i + 2);
|
||||
const segmentData = {
|
||||
feature: feature,
|
||||
segment: segment,
|
||||
};
|
||||
this.rBush_.insert(boundingExtent(segment), segmentData);
|
||||
segments.push(coordinates.slice(i, i + 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../Feature.js").default} feature Feature
|
||||
* @param {Array<Array<import('../coordinate.js').Coordinate>>} segments Segments
|
||||
* @param {import("../geom/Point.js").default} geometry Geometry.
|
||||
* @private
|
||||
*/
|
||||
writePointGeometry_(feature, geometry) {
|
||||
const coordinates = geometry.getCoordinates();
|
||||
const segmentData = {
|
||||
feature: feature,
|
||||
segment: [coordinates, coordinates],
|
||||
};
|
||||
this.rBush_.insert(geometry.getExtent(), segmentData);
|
||||
segmentPointGemetry_(segments, geometry) {
|
||||
segments.push([geometry.getCoordinates()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {import("../Feature.js").default} feature Feature
|
||||
* @param {Array<Array<import('../coordinate.js').Coordinate>>} segments Segments
|
||||
* @param {import("../geom/Polygon.js").default} geometry Geometry.
|
||||
* @private
|
||||
*/
|
||||
writePolygonGeometry_(feature, geometry) {
|
||||
segmentPolygonGemetry_(segments, geometry) {
|
||||
const rings = geometry.getCoordinates();
|
||||
for (let j = 0, jj = rings.length; j < jj; ++j) {
|
||||
const coordinates = rings[j];
|
||||
for (let i = 0, ii = coordinates.length - 1; i < ii; ++i) {
|
||||
const segment = coordinates.slice(i, i + 2);
|
||||
const segmentData = {
|
||||
feature: feature,
|
||||
segment: segment,
|
||||
};
|
||||
this.rBush_.insert(boundingExtent(segment), segmentData);
|
||||
segments.push(coordinates.slice(i, i + 2));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,7 +371,7 @@ class Layer extends BaseLayer {
|
||||
|
||||
/**
|
||||
* Get the renderer for this layer.
|
||||
* @return {RendererType} The layer renderer.
|
||||
* @return {RendererType|null} The layer renderer.
|
||||
*/
|
||||
getRenderer() {
|
||||
if (!this.renderer_) {
|
||||
|
||||
@@ -620,7 +620,7 @@ export function fromUserCoordinate(coordinate, destProjection) {
|
||||
showCoordinateWarning = false;
|
||||
// eslint-disable-next-line no-console
|
||||
console.warn(
|
||||
'Call useGeographic() ol/proj once to work with [longitude, latitude] coordinates.'
|
||||
'Call useGeographic() from ol/proj once to work with [longitude, latitude] coordinates.'
|
||||
);
|
||||
}
|
||||
return coordinate;
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
* @module ol/renderer/canvas/ImageLayer
|
||||
*/
|
||||
import CanvasLayerRenderer from './Layer.js';
|
||||
import ImageState from '../../ImageState.js';
|
||||
import ViewHint from '../../ViewHint.js';
|
||||
import {ENABLE_RASTER_REPROJECTION} from '../../reproj/common.js';
|
||||
import {IMAGE_SMOOTHING_DISABLED, IMAGE_SMOOTHING_ENABLED} from './common.js';
|
||||
@@ -91,10 +92,12 @@ class CanvasImageLayerRenderer extends CanvasLayerRenderer {
|
||||
pixelRatio,
|
||||
projection
|
||||
);
|
||||
if (image && this.loadImage(image)) {
|
||||
this.image_ = image;
|
||||
} else {
|
||||
this.image_ = null;
|
||||
if (image) {
|
||||
if (this.loadImage(image)) {
|
||||
this.image_ = image;
|
||||
} else if (image.getState() === ImageState.EMPTY) {
|
||||
this.image_ = null;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
this.image_ = null;
|
||||
|
||||
@@ -484,7 +484,7 @@ class Text {
|
||||
/**
|
||||
* Set the text.
|
||||
*
|
||||
* @param {string|undefined} text Text.
|
||||
* @param {string|Array<string>|undefined} text Text.
|
||||
* @api
|
||||
*/
|
||||
setText(text) {
|
||||
|
||||
@@ -491,6 +491,18 @@ describe('ol/Map', function () {
|
||||
})
|
||||
);
|
||||
});
|
||||
it('ignores invisible layers', function (done) {
|
||||
map.getLayers().forEach(function (layer, i) {
|
||||
layer.setVisible(i === 4);
|
||||
});
|
||||
map.setView(
|
||||
new View({
|
||||
center: [0, 0],
|
||||
zoom: 0,
|
||||
})
|
||||
);
|
||||
map.once('rendercomplete', () => done());
|
||||
});
|
||||
});
|
||||
|
||||
describe('#getFeaturesAtPixel', function () {
|
||||
|
||||
@@ -7,4 +7,23 @@ describe('ol.control.FullScreen', function () {
|
||||
expect(instance).to.be.an(FullScreen);
|
||||
});
|
||||
});
|
||||
|
||||
describe('the fullscreen button', function () {
|
||||
describe('when inactiveClassName is not set', function () {
|
||||
it('is created with the default inactive classname set on the button', function () {
|
||||
const instance = new FullScreen();
|
||||
const button = instance.button_;
|
||||
expect(button.className).to.equal('ol-full-screen-false');
|
||||
});
|
||||
});
|
||||
describe('when inactiveClassName is set', function () {
|
||||
it('is created with the desired inactive classnames set on the button', function () {
|
||||
const instance = new FullScreen({
|
||||
inactiveClassName: 'foo bar',
|
||||
});
|
||||
const button = instance.button_;
|
||||
expect(button.className).to.equal('foo bar');
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -122,6 +122,27 @@ describe('ol.interaction.Snap', function () {
|
||||
expect(event.coordinate).to.eql([10, 0]);
|
||||
});
|
||||
|
||||
it('snaps to vertex on line', function () {
|
||||
const line = new Feature(
|
||||
new LineString([
|
||||
[0, 0],
|
||||
[50, 0],
|
||||
])
|
||||
);
|
||||
const point = new Feature(new Point([5, 0]));
|
||||
const snap = new Snap({
|
||||
features: new Collection([line, point]),
|
||||
});
|
||||
snap.setMap(map);
|
||||
const event = {
|
||||
pixel: [3 + width / 2, height / 2],
|
||||
coordinate: [3, 0],
|
||||
map: map,
|
||||
};
|
||||
snap.handleEvent(event);
|
||||
expect(event.coordinate).to.eql([5, 0]);
|
||||
});
|
||||
|
||||
it('snaps to circle', function () {
|
||||
const circle = new Feature(new Circle([0, 0], 10));
|
||||
const snapInteraction = new Snap({
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
import CanvasImageLayerRenderer from '../../../../../../src/ol/renderer/canvas/ImageLayer.js';
|
||||
import Feature from '../../../../../../src/ol/Feature.js';
|
||||
import ImageLayer from '../../../../../../src/ol/layer/Image.js';
|
||||
import ImageState from '../../../../../../src/ol/ImageState.js';
|
||||
import ImageWrapper from '../../../../../../src/ol/Image.js';
|
||||
import Map from '../../../../../../src/ol/Map.js';
|
||||
import Point from '../../../../../../src/ol/geom/Point.js';
|
||||
import Projection from '../../../../../../src/ol/proj/Projection.js';
|
||||
@@ -446,5 +448,18 @@ describe('ol/renderer/canvas/ImageLayer', function () {
|
||||
}
|
||||
});
|
||||
});
|
||||
it('resets image when empty', function (done) {
|
||||
const frameState = createLayerFrameState([0, 0, 100, 100]);
|
||||
layer.getSource().on('imageloadend', function () {
|
||||
if (renderer.prepareFrame(frameState)) {
|
||||
renderer.renderFrame(frameState, null);
|
||||
}
|
||||
expect(renderer.image_).to.be.a(ImageWrapper);
|
||||
renderer.image_.state = ImageState.EMPTY;
|
||||
expect(renderer.prepareFrame(frameState)).to.be(false);
|
||||
expect(renderer.image_).to.be(null);
|
||||
done();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -930,5 +930,13 @@ describe('ol/proj.js', function () {
|
||||
view.setCenter([15, 47]);
|
||||
expect(callCount).to.be(0);
|
||||
});
|
||||
it('is not shown when view projection is configured', function () {
|
||||
const view = new View({
|
||||
projection: 'EPSG:4326',
|
||||
center: [16, 48],
|
||||
});
|
||||
view.setCenter([15, 47]);
|
||||
expect(callCount).to.be(0);
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user