Merge pull request #5995 from KlausBenndorf/hitTolerance
Add hit tolerance parameter to ol.Map#forEachFeatureAtPixel
This commit is contained in:
@@ -2,6 +2,32 @@
|
||||
|
||||
### Next release
|
||||
|
||||
#### `ol.Map#forEachFeatureAtPixel` and `ol.Map#hasFeatureAtPixel` parameters have changed
|
||||
|
||||
If you are using the layer filter of one of these methods, please note that you now have to pass in the layer filter via an `ol.AtPixelOptions` object. If you are not using the layer filter the usage has not changed.
|
||||
|
||||
Old syntax:
|
||||
```
|
||||
map.forEachFeatureAtPixel(pixel, callback, callbackThis, layerFilterFn, layerFilterThis);
|
||||
|
||||
map.hasFeatureAtPixel(pixel, layerFilterFn, layerFilterThis);
|
||||
```
|
||||
|
||||
New syntax:
|
||||
```
|
||||
map.forEachFeatureAtPixel(pixel, callback, {
|
||||
layerFilter: layerFilterFn
|
||||
});
|
||||
|
||||
map.hasFeatureAtPixel(pixel, {
|
||||
layerFilter: layerFilterFn
|
||||
});
|
||||
```
|
||||
|
||||
To bind a function to a this, please use the bind method of the function (See: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind).
|
||||
|
||||
This change is due to the introduction of the `hitTolerance` parameter which can be passed in via this `ol.AtPixelOptions` object, too.
|
||||
|
||||
#### Use `view.animate()` instead of `map.beforeRender()` and `ol.animation` functions
|
||||
|
||||
The `map.beforeRender()` and `ol.animation` functions have been deprecated in favor of a new `view.animate()` function. Use of the deprecated functions will result in a warning during development. These functions are subject to removal in an upcoming release.
|
||||
|
||||
@@ -18,5 +18,13 @@ tags: "select, vector"
|
||||
<option value="altclick">Alt+Click</option>
|
||||
<option value="none">None</option>
|
||||
</select>
|
||||
<span id="status"> 0 selected features</span>
|
||||
<span id="status"> 0 selected features</span>
|
||||
<br />
|
||||
<label>Hit tolerance for selecting features </label>
|
||||
<select id="hitTolerance" class="form-control">
|
||||
<option value="0" selected>0 Pixels</option>
|
||||
<option value="5">5 Pixels</option>
|
||||
<option value="10">10 Pixels</option>
|
||||
</select>
|
||||
<canvas id="circle" style="vertical-align: middle"/>
|
||||
</form>
|
||||
|
||||
@@ -31,23 +31,28 @@ var map = new ol.Map({
|
||||
var select = null; // ref to currently selected interaction
|
||||
|
||||
// select interaction working on "singleclick"
|
||||
var selectSingleClick = new ol.interaction.Select();
|
||||
var selectSingleClick = new ol.interaction.Select({
|
||||
multi: true // multi is used in this example if hitTolerance > 0
|
||||
});
|
||||
|
||||
// select interaction working on "click"
|
||||
var selectClick = new ol.interaction.Select({
|
||||
condition: ol.events.condition.click
|
||||
condition: ol.events.condition.click,
|
||||
multi: true
|
||||
});
|
||||
|
||||
// select interaction working on "pointermove"
|
||||
var selectPointerMove = new ol.interaction.Select({
|
||||
condition: ol.events.condition.pointerMove
|
||||
condition: ol.events.condition.pointerMove,
|
||||
multi: true
|
||||
});
|
||||
|
||||
var selectAltClick = new ol.interaction.Select({
|
||||
condition: function(mapBrowserEvent) {
|
||||
return ol.events.condition.click(mapBrowserEvent) &&
|
||||
ol.events.condition.altKeyOnly(mapBrowserEvent);
|
||||
}
|
||||
},
|
||||
multi: true
|
||||
});
|
||||
|
||||
var selectElement = document.getElementById('type');
|
||||
@@ -85,3 +90,27 @@ var changeInteraction = function() {
|
||||
*/
|
||||
selectElement.onchange = changeInteraction;
|
||||
changeInteraction();
|
||||
|
||||
var selectHitToleranceElement = document.getElementById('hitTolerance');
|
||||
var circleCanvas = document.getElementById('circle');
|
||||
|
||||
var changeHitTolerance = function() {
|
||||
var value = parseInt(selectHitToleranceElement.value, 10);
|
||||
selectSingleClick.setHitTolerance(value);
|
||||
selectClick.setHitTolerance(value);
|
||||
selectPointerMove.setHitTolerance(value);
|
||||
selectAltClick.setHitTolerance(value);
|
||||
|
||||
var size = 2 * value + 2;
|
||||
circleCanvas.width = size;
|
||||
circleCanvas.height = size;
|
||||
var ctx = circleCanvas.getContext('2d');
|
||||
ctx.clearRect(0, 0, size, size);
|
||||
ctx.beginPath();
|
||||
ctx.arc(value + 1, value + 1, value + 0.5, 0, 2 * Math.PI);
|
||||
ctx.fill();
|
||||
ctx.stroke();
|
||||
};
|
||||
|
||||
selectHitToleranceElement.onchange = changeHitTolerance;
|
||||
changeHitTolerance();
|
||||
|
||||
@@ -302,6 +302,36 @@ olx.MapOptions.prototype.target;
|
||||
olx.MapOptions.prototype.view;
|
||||
|
||||
|
||||
/**
|
||||
* Object literal with options for the {@link ol.Map#forEachFeatureAtPixel} and
|
||||
* {@link ol.Map#hasFeatureAtPixel} methods.
|
||||
* @typedef {{layerFilter: ((function(ol.layer.Layer): boolean)|undefined),
|
||||
* hitTolerance: (number|undefined)}}
|
||||
*/
|
||||
olx.AtPixelOptions;
|
||||
|
||||
|
||||
/**
|
||||
* Layer filter function. The filter function will receive one argument, the
|
||||
* {@link ol.layer.Layer layer-candidate} and it should return a boolean value.
|
||||
* Only layers which are visible and for which this function returns `true`
|
||||
* will be tested for features. By default, all visible layers will be tested.
|
||||
* @type {((function(ol.layer.Layer): boolean)|undefined)}
|
||||
* @api stable
|
||||
*/
|
||||
olx.AtPixelOptions.prototype.layerFilter;
|
||||
|
||||
|
||||
/**
|
||||
* Hit-detection tolerance in pixels. Pixels inside the radius around the given position
|
||||
* will be checked for features. This only works for the canvas renderer and
|
||||
* not for WebGL.
|
||||
* @type {number|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.AtPixelOptions.prototype.hitTolerance;
|
||||
|
||||
|
||||
/**
|
||||
* Object literal with config options for the overlay.
|
||||
* @typedef {{id: (number|string|undefined),
|
||||
@@ -2871,7 +2901,8 @@ olx.interaction.ExtentOptions.prototype.wrapX;
|
||||
/**
|
||||
* @typedef {{
|
||||
* features: (ol.Collection.<ol.Feature>|undefined),
|
||||
* layers: (undefined|Array.<ol.layer.Layer>|function(ol.layer.Layer): boolean)
|
||||
* layers: (undefined|Array.<ol.layer.Layer>|function(ol.layer.Layer): boolean),
|
||||
* hitTolerance: (number|undefined)
|
||||
* }}
|
||||
*/
|
||||
olx.interaction.TranslateOptions;
|
||||
@@ -2898,6 +2929,16 @@ olx.interaction.TranslateOptions.prototype.features;
|
||||
olx.interaction.TranslateOptions.prototype.layers;
|
||||
|
||||
|
||||
/**
|
||||
* Hit-detection tolerance. Pixels inside the radius around the given position
|
||||
* will be checked for features. This only works for the canvas renderer and
|
||||
* not for WebGL.
|
||||
* @type {number|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.interaction.TranslateOptions.prototype.hitTolerance;
|
||||
|
||||
|
||||
/**
|
||||
* @typedef {{condition: (ol.EventsConditionType|undefined),
|
||||
* duration: (number|undefined),
|
||||
@@ -3173,7 +3214,8 @@ olx.interaction.PointerOptions.prototype.handleUpEvent;
|
||||
* multi: (boolean|undefined),
|
||||
* features: (ol.Collection.<ol.Feature>|undefined),
|
||||
* filter: (ol.SelectFilterFunction|undefined),
|
||||
* wrapX: (boolean|undefined)}}
|
||||
* wrapX: (boolean|undefined),
|
||||
* hitTolerance: (number|undefined)}}
|
||||
*/
|
||||
olx.interaction.SelectOptions;
|
||||
|
||||
@@ -3287,6 +3329,16 @@ olx.interaction.SelectOptions.prototype.filter;
|
||||
olx.interaction.SelectOptions.prototype.wrapX;
|
||||
|
||||
|
||||
/**
|
||||
* Hit-detection tolerance. Pixels inside the radius around the given position
|
||||
* will be checked for features. This only works for the canvas renderer and
|
||||
* not for WebGL.
|
||||
* @type {number|undefined}
|
||||
* @api
|
||||
*/
|
||||
olx.interaction.SelectOptions.prototype.hitTolerance;
|
||||
|
||||
|
||||
/**
|
||||
* Options for snap
|
||||
* @typedef {{
|
||||
@@ -7623,7 +7675,7 @@ olx.view.FitOptions.prototype.maxZoom;
|
||||
|
||||
|
||||
/**
|
||||
* The duration of the animation in milliseconds. By default, there is no
|
||||
* The duration of the animation in milliseconds. By default, there is no
|
||||
* animations.
|
||||
* @type {number|undefined}
|
||||
* @api
|
||||
|
||||
@@ -82,6 +82,12 @@ ol.interaction.Select = function(opt_options) {
|
||||
this.filter_ = options.filter ? options.filter :
|
||||
ol.functions.TRUE;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.hitTolerance_ = options.hitTolerance ? options.hitTolerance : 0;
|
||||
|
||||
var featureOverlay = new ol.layer.Vector({
|
||||
source: new ol.source.Vector({
|
||||
useSpatialIndex: false,
|
||||
@@ -160,6 +166,16 @@ ol.interaction.Select.prototype.getFeatures = function() {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the Hit-detection tolerance.
|
||||
* @returns {number} Hit tolerance in pixels.
|
||||
* @api
|
||||
*/
|
||||
ol.interaction.Select.prototype.getHitTolerance = function() {
|
||||
return this.hitTolerance_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the associated {@link ol.layer.Vector vectorlayer} of
|
||||
* the (last) selected feature. Note that this will not work with any
|
||||
@@ -201,7 +217,7 @@ ol.interaction.Select.handleEvent = function(mapBrowserEvent) {
|
||||
// the pixel.
|
||||
ol.obj.clear(this.featureLayerAssociation_);
|
||||
map.forEachFeatureAtPixel(mapBrowserEvent.pixel,
|
||||
/**
|
||||
(/**
|
||||
* @param {ol.Feature|ol.render.Feature} feature Feature.
|
||||
* @param {ol.layer.Layer} layer Layer.
|
||||
* @return {boolean|undefined} Continue to iterate over the features.
|
||||
@@ -212,7 +228,10 @@ ol.interaction.Select.handleEvent = function(mapBrowserEvent) {
|
||||
this.addFeatureLayerAssociation_(feature, layer);
|
||||
return !this.multi_;
|
||||
}
|
||||
}, this, this.layerFilter_);
|
||||
}).bind(this), {
|
||||
layerFilter: this.layerFilter_,
|
||||
hitTolerance: this.hitTolerance_
|
||||
});
|
||||
var i;
|
||||
for (i = features.getLength() - 1; i >= 0; --i) {
|
||||
var feature = features.item(i);
|
||||
@@ -231,7 +250,7 @@ ol.interaction.Select.handleEvent = function(mapBrowserEvent) {
|
||||
} else {
|
||||
// Modify the currently selected feature(s).
|
||||
map.forEachFeatureAtPixel(mapBrowserEvent.pixel,
|
||||
/**
|
||||
(/**
|
||||
* @param {ol.Feature|ol.render.Feature} feature Feature.
|
||||
* @param {ol.layer.Layer} layer Layer.
|
||||
* @return {boolean|undefined} Continue to iterate over the features.
|
||||
@@ -249,7 +268,10 @@ ol.interaction.Select.handleEvent = function(mapBrowserEvent) {
|
||||
}
|
||||
return !this.multi_;
|
||||
}
|
||||
}, this, this.layerFilter_);
|
||||
}).bind(this), {
|
||||
layerFilter: this.layerFilter_,
|
||||
hitTolerance: this.hitTolerance_
|
||||
});
|
||||
var j;
|
||||
for (j = deselected.length - 1; j >= 0; --j) {
|
||||
features.remove(deselected[j]);
|
||||
@@ -265,6 +287,18 @@ ol.interaction.Select.handleEvent = function(mapBrowserEvent) {
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Hit-detection tolerance. Pixels inside the radius around the given position
|
||||
* will be checked for features. This only works for the canvas renderer and
|
||||
* not for WebGL.
|
||||
* @param {number} hitTolerance Hit tolerance in pixels.
|
||||
* @api
|
||||
*/
|
||||
ol.interaction.Select.prototype.setHitTolerance = function(hitTolerance) {
|
||||
this.hitTolerance_ = hitTolerance;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Remove the interaction from its current map, if any, and attach it to a new
|
||||
* map, if any. Pass `null` to just remove the interaction from the current map.
|
||||
|
||||
@@ -70,6 +70,12 @@ ol.interaction.Translate = function(opt_options) {
|
||||
*/
|
||||
this.layerFilter_ = layerFilter;
|
||||
|
||||
/**
|
||||
* @private
|
||||
* @type {number}
|
||||
*/
|
||||
this.hitTolerance_ = options.hitTolerance ? options.hitTolerance : 0;
|
||||
|
||||
/**
|
||||
* @type {ol.Feature}
|
||||
* @private
|
||||
@@ -197,7 +203,32 @@ ol.interaction.Translate.prototype.featuresAtPixel_ = function(pixel, map) {
|
||||
ol.array.includes(this.features_.getArray(), feature)) {
|
||||
return feature;
|
||||
}
|
||||
}, this, this.layerFilter_);
|
||||
}.bind(this), {
|
||||
layerFilter: this.layerFilter_,
|
||||
hitTolerance: this.hitTolerance_
|
||||
});
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Returns the Hit-detection tolerance.
|
||||
* @returns {number} Hit tolerance in pixels.
|
||||
* @api
|
||||
*/
|
||||
ol.interaction.Translate.prototype.getHitTolerance = function() {
|
||||
return this.hitTolerance_;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Hit-detection tolerance. Pixels inside the radius around the given position
|
||||
* will be checked for features. This only works for the canvas renderer and
|
||||
* not for WebGL.
|
||||
* @param {number} hitTolerance Hit tolerance in pixels.
|
||||
* @api
|
||||
*/
|
||||
ol.interaction.Translate.prototype.setHitTolerance = function(hitTolerance) {
|
||||
this.hitTolerance_ = hitTolerance;
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -567,31 +567,25 @@ ol.Map.prototype.disposeInternal = function() {
|
||||
* the {@link ol.layer.Layer layer} of the feature and will be null for
|
||||
* unmanaged layers. To stop detection, callback functions can return a
|
||||
* truthy value.
|
||||
* @param {S=} opt_this Value to use as `this` when executing `callback`.
|
||||
* @param {(function(this: U, ol.layer.Layer): boolean)=} opt_layerFilter Layer
|
||||
* filter function. The filter function will receive one argument, the
|
||||
* {@link ol.layer.Layer layer-candidate} and it should return a boolean
|
||||
* value. Only layers which are visible and for which this function returns
|
||||
* `true` will be tested for features. By default, all visible layers will
|
||||
* be tested.
|
||||
* @param {U=} opt_this2 Value to use as `this` when executing `layerFilter`.
|
||||
* @param {olx.AtPixelOptions=} opt_options Optional options.
|
||||
* @return {T|undefined} Callback result, i.e. the return value of last
|
||||
* callback execution, or the first truthy callback return value.
|
||||
* @template S,T,U
|
||||
* @template S,T
|
||||
* @api stable
|
||||
*/
|
||||
ol.Map.prototype.forEachFeatureAtPixel = function(pixel, callback, opt_this, opt_layerFilter, opt_this2) {
|
||||
ol.Map.prototype.forEachFeatureAtPixel = function(pixel, callback, opt_options) {
|
||||
if (!this.frameState_) {
|
||||
return;
|
||||
}
|
||||
var coordinate = this.getCoordinateFromPixel(pixel);
|
||||
var thisArg = opt_this !== undefined ? opt_this : null;
|
||||
var layerFilter = opt_layerFilter !== undefined ?
|
||||
opt_layerFilter : ol.functions.TRUE;
|
||||
var thisArg2 = opt_this2 !== undefined ? opt_this2 : null;
|
||||
opt_options = opt_options !== undefined ? opt_options : {};
|
||||
var hitTolerance = opt_options.hitTolerance !== undefined ?
|
||||
opt_options.hitTolerance * this.frameState_.pixelRatio : 0;
|
||||
var layerFilter = opt_options.layerFilter !== undefined ?
|
||||
opt_options.layerFilter : ol.functions.TRUE;
|
||||
return this.renderer_.forEachFeatureAtCoordinate(
|
||||
coordinate, this.frameState_, callback, thisArg,
|
||||
layerFilter, thisArg2);
|
||||
coordinate, this.frameState_, hitTolerance, callback, null,
|
||||
layerFilter, null);
|
||||
};
|
||||
|
||||
|
||||
@@ -637,27 +631,23 @@ ol.Map.prototype.forEachLayerAtPixel = function(pixel, callback, opt_this, opt_l
|
||||
* Detect if features intersect a pixel on the viewport. Layers included in the
|
||||
* detection can be configured through `opt_layerFilter`.
|
||||
* @param {ol.Pixel} pixel Pixel.
|
||||
* @param {(function(this: U, ol.layer.Layer): boolean)=} opt_layerFilter Layer
|
||||
* filter function. The filter function will receive one argument, the
|
||||
* {@link ol.layer.Layer layer-candidate} and it should return a boolean
|
||||
* value. Only layers which are visible and for which this function returns
|
||||
* `true` will be tested for features. By default, all visible layers will
|
||||
* be tested.
|
||||
* @param {U=} opt_this Value to use as `this` when executing `layerFilter`.
|
||||
* @param {olx.AtPixelOptions=} opt_options Optional options.
|
||||
* @return {boolean} Is there a feature at the given pixel?
|
||||
* @template U
|
||||
* @api
|
||||
*/
|
||||
ol.Map.prototype.hasFeatureAtPixel = function(pixel, opt_layerFilter, opt_this) {
|
||||
ol.Map.prototype.hasFeatureAtPixel = function(pixel, opt_options) {
|
||||
if (!this.frameState_) {
|
||||
return false;
|
||||
}
|
||||
var coordinate = this.getCoordinateFromPixel(pixel);
|
||||
var layerFilter = opt_layerFilter !== undefined ?
|
||||
opt_layerFilter : ol.functions.TRUE;
|
||||
var thisArg = opt_this !== undefined ? opt_this : null;
|
||||
opt_options = opt_options !== undefined ? opt_options : {};
|
||||
var layerFilter = opt_options.layerFilter !== undefined ?
|
||||
opt_options.layerFilter : ol.functions.TRUE;
|
||||
var hitTolerance = opt_options.hitTolerance !== undefined ?
|
||||
opt_options.hitTolerance * this.frameState_.pixelRatio : 0;
|
||||
return this.renderer_.hasFeatureAtCoordinate(
|
||||
coordinate, this.frameState_, layerFilter, thisArg);
|
||||
coordinate, this.frameState_, hitTolerance, layerFilter, null);
|
||||
};
|
||||
|
||||
|
||||
|
||||
@@ -77,11 +77,90 @@ ol.render.canvas.ReplayGroup = function(
|
||||
* @type {ol.Transform}
|
||||
*/
|
||||
this.hitDetectionTransform_ = ol.transform.create();
|
||||
|
||||
};
|
||||
ol.inherits(ol.render.canvas.ReplayGroup, ol.render.ReplayGroup);
|
||||
|
||||
|
||||
/**
|
||||
* This cache is used for storing calculated pixel circles for increasing performance.
|
||||
* It is a static property to allow each Replaygroup to access it.
|
||||
* @type {Object.<number, Array.<Array.<(boolean|undefined)>>>}
|
||||
* @private
|
||||
*/
|
||||
ol.render.canvas.ReplayGroup.circleArrayCache_ = {
|
||||
0: [[true]]
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This method fills a row in the array from the given coordinate to the
|
||||
* middle with `true`.
|
||||
* @param {Array.<Array.<(boolean|undefined)>>} array The array that will be altered.
|
||||
* @param {number} x X coordinate.
|
||||
* @param {number} y Y coordinate.
|
||||
* @private
|
||||
*/
|
||||
ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_ = function(array, x, y) {
|
||||
var i;
|
||||
var radius = Math.floor(array.length / 2);
|
||||
if (x >= radius) {
|
||||
for (i = radius; i < x; i++) {
|
||||
array[i][y] = true;
|
||||
}
|
||||
} else if (x < radius) {
|
||||
for (i = x + 1; i < radius; i++) {
|
||||
array[i][y] = true;
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* This methods creates a circle inside a fitting array. Points inside the
|
||||
* circle are marked by true, points on the outside are undefined.
|
||||
* It uses the midpoint circle algorithm.
|
||||
* A cache is used to increase performance.
|
||||
* @param {number} radius Radius.
|
||||
* @returns {Array.<Array.<(boolean|undefined)>>} An array with marked circle points.
|
||||
* @private
|
||||
*/
|
||||
ol.render.canvas.ReplayGroup.getCircleArray_ = function(radius) {
|
||||
if (ol.render.canvas.ReplayGroup.circleArrayCache_[radius] !== undefined) {
|
||||
return ol.render.canvas.ReplayGroup.circleArrayCache_[radius];
|
||||
}
|
||||
|
||||
var arraySize = radius * 2 + 1;
|
||||
var arr = new Array(arraySize);
|
||||
for (var i = 0; i < arraySize; i++) {
|
||||
arr[i] = new Array(arraySize);
|
||||
}
|
||||
|
||||
var x = radius;
|
||||
var y = 0;
|
||||
var error = 0;
|
||||
|
||||
while (x >= y) {
|
||||
ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius + x, radius + y);
|
||||
ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius + y, radius + x);
|
||||
ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius - y, radius + x);
|
||||
ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius - x, radius + y);
|
||||
ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius - x, radius - y);
|
||||
ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius - y, radius - x);
|
||||
ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius + y, radius - x);
|
||||
ol.render.canvas.ReplayGroup.fillCircleArrayRowToMiddle_(arr, radius + x, radius - y);
|
||||
|
||||
y++;
|
||||
error += 1 + 2 * y;
|
||||
if (2 * (error - x) + 1 > 0) {
|
||||
x -= 1;
|
||||
error += 1 - 2 * x;
|
||||
}
|
||||
}
|
||||
|
||||
ol.render.canvas.ReplayGroup.circleArrayCache_[radius] = arr;
|
||||
return arr;
|
||||
};
|
||||
|
||||
/**
|
||||
* FIXME empty description for jsdoc
|
||||
*/
|
||||
@@ -101,6 +180,7 @@ ol.render.canvas.ReplayGroup.prototype.finish = function() {
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} rotation Rotation.
|
||||
* @param {number} hitTolerance Hit tolerance in pixels.
|
||||
* @param {Object.<string, boolean>} skippedFeaturesHash Ids of features
|
||||
* to skip.
|
||||
* @param {function((ol.Feature|ol.render.Feature)): T} callback Feature
|
||||
@@ -109,16 +189,23 @@ ol.render.canvas.ReplayGroup.prototype.finish = function() {
|
||||
* @template T
|
||||
*/
|
||||
ol.render.canvas.ReplayGroup.prototype.forEachFeatureAtCoordinate = function(
|
||||
coordinate, resolution, rotation, skippedFeaturesHash, callback) {
|
||||
coordinate, resolution, rotation, hitTolerance, skippedFeaturesHash, callback) {
|
||||
|
||||
hitTolerance = Math.round(hitTolerance);
|
||||
var contextSize = hitTolerance * 2 + 1;
|
||||
var transform = ol.transform.compose(this.hitDetectionTransform_,
|
||||
0.5, 0.5,
|
||||
hitTolerance + 0.5, hitTolerance + 0.5,
|
||||
1 / resolution, -1 / resolution,
|
||||
-rotation,
|
||||
-coordinate[0], -coordinate[1]);
|
||||
|
||||
var context = this.hitDetectionContext_;
|
||||
context.clearRect(0, 0, 1, 1);
|
||||
|
||||
if (context.canvas.width !== contextSize || context.canvas.height !== contextSize) {
|
||||
context.canvas.width = contextSize;
|
||||
context.canvas.height = contextSize;
|
||||
} else {
|
||||
context.clearRect(0, 0, contextSize, contextSize);
|
||||
}
|
||||
|
||||
/**
|
||||
* @type {ol.Extent}
|
||||
@@ -127,9 +214,11 @@ ol.render.canvas.ReplayGroup.prototype.forEachFeatureAtCoordinate = function(
|
||||
if (this.renderBuffer_ !== undefined) {
|
||||
hitExtent = ol.extent.createEmpty();
|
||||
ol.extent.extendCoordinate(hitExtent, coordinate);
|
||||
ol.extent.buffer(hitExtent, resolution * this.renderBuffer_, hitExtent);
|
||||
ol.extent.buffer(hitExtent, resolution * (this.renderBuffer_ + hitTolerance), hitExtent);
|
||||
}
|
||||
|
||||
var mask = ol.render.canvas.ReplayGroup.getCircleArray_(hitTolerance);
|
||||
|
||||
return this.replayHitDetection_(context, transform, rotation,
|
||||
skippedFeaturesHash,
|
||||
/**
|
||||
@@ -137,13 +226,21 @@ ol.render.canvas.ReplayGroup.prototype.forEachFeatureAtCoordinate = function(
|
||||
* @return {?} Callback result.
|
||||
*/
|
||||
function(feature) {
|
||||
var imageData = context.getImageData(0, 0, 1, 1).data;
|
||||
if (imageData[3] > 0) {
|
||||
var result = callback(feature);
|
||||
if (result) {
|
||||
return result;
|
||||
var imageData = context.getImageData(0, 0, contextSize, contextSize).data;
|
||||
for (var i = 0; i < contextSize; i++) {
|
||||
for (var j = 0; j < contextSize; j++) {
|
||||
if (mask[i][j]) {
|
||||
if (imageData[(j * contextSize + i) * 4 + 3] > 0) {
|
||||
var result = callback(feature);
|
||||
if (result) {
|
||||
return result;
|
||||
} else {
|
||||
context.clearRect(0, 0, contextSize, contextSize);
|
||||
return undefined;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
context.clearRect(0, 0, 1, 1);
|
||||
}
|
||||
}, hitExtent);
|
||||
};
|
||||
|
||||
@@ -98,14 +98,14 @@ ol.renderer.canvas.IntermediateCanvas.prototype.getImageTransform = function() {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.canvas.IntermediateCanvas.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, callback, thisArg) {
|
||||
ol.renderer.canvas.IntermediateCanvas.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, callback, thisArg) {
|
||||
var layer = this.getLayer();
|
||||
var source = layer.getSource();
|
||||
var resolution = frameState.viewState.resolution;
|
||||
var rotation = frameState.viewState.rotation;
|
||||
var skippedFeatureUids = frameState.skippedFeatureUids;
|
||||
return source.forEachFeatureAtCoordinate(
|
||||
coordinate, resolution, rotation, skippedFeatureUids,
|
||||
coordinate, resolution, rotation, hitTolerance, skippedFeatureUids,
|
||||
/**
|
||||
* @param {ol.Feature|ol.render.Feature} feature Feature.
|
||||
* @return {?} Callback result.
|
||||
|
||||
@@ -106,7 +106,7 @@ ol.renderer.canvas.Layer.prototype.dispatchComposeEvent_ = function(type, contex
|
||||
*/
|
||||
ol.renderer.canvas.Layer.prototype.forEachLayerAtCoordinate = function(coordinate, frameState, callback, thisArg) {
|
||||
var hasFeature = this.forEachFeatureAtCoordinate(
|
||||
coordinate, frameState, ol.functions.TRUE, this);
|
||||
coordinate, frameState, 0, ol.functions.TRUE, this);
|
||||
|
||||
if (hasFeature) {
|
||||
return callback.call(thisArg, this.getLayer(), null);
|
||||
|
||||
@@ -177,7 +177,7 @@ ol.renderer.canvas.VectorLayer.prototype.composeFrame = function(frameState, lay
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, callback, thisArg) {
|
||||
ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, callback, thisArg) {
|
||||
if (!this.replayGroup_) {
|
||||
return undefined;
|
||||
} else {
|
||||
@@ -187,7 +187,7 @@ ol.renderer.canvas.VectorLayer.prototype.forEachFeatureAtCoordinate = function(c
|
||||
/** @type {Object.<string, boolean>} */
|
||||
var features = {};
|
||||
return this.replayGroup_.forEachFeatureAtCoordinate(coordinate, resolution,
|
||||
rotation, {},
|
||||
rotation, hitTolerance, {},
|
||||
/**
|
||||
* @param {ol.Feature|ol.render.Feature} feature Feature.
|
||||
* @return {?} Callback result.
|
||||
|
||||
@@ -176,9 +176,10 @@ ol.renderer.canvas.VectorTileLayer.prototype.drawTileImage = function(
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.canvas.VectorTileLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, callback, thisArg) {
|
||||
ol.renderer.canvas.VectorTileLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, callback, thisArg) {
|
||||
var resolution = frameState.viewState.resolution;
|
||||
var rotation = frameState.viewState.rotation;
|
||||
hitTolerance = hitTolerance == undefined ? 0 : hitTolerance;
|
||||
var layer = this.getLayer();
|
||||
/** @type {Object.<string, boolean>} */
|
||||
var features = {};
|
||||
@@ -195,7 +196,7 @@ ol.renderer.canvas.VectorTileLayer.prototype.forEachFeatureAtCoordinate = functi
|
||||
tile = replayables[i];
|
||||
tileCoord = tile.tileCoord;
|
||||
tileExtent = source.getTileGrid().getTileCoordExtent(tileCoord, this.tmpExtent);
|
||||
if (!ol.extent.containsCoordinate(tileExtent, coordinate)) {
|
||||
if (!ol.extent.containsCoordinate(ol.extent.buffer(tileExtent, hitTolerance * resolution), coordinate)) {
|
||||
continue;
|
||||
}
|
||||
if (tile.getProjection().getUnits() === ol.proj.Units.TILE_PIXELS) {
|
||||
@@ -212,7 +213,7 @@ ol.renderer.canvas.VectorTileLayer.prototype.forEachFeatureAtCoordinate = functi
|
||||
}
|
||||
replayGroup = tile.getReplayState().replayGroup;
|
||||
found = found || replayGroup.forEachFeatureAtCoordinate(
|
||||
tileSpaceCoordinate, resolution, rotation, {},
|
||||
tileSpaceCoordinate, resolution, rotation, hitTolerance, {},
|
||||
/**
|
||||
* @param {ol.Feature|ol.render.Feature} feature Feature.
|
||||
* @return {?} Callback result.
|
||||
|
||||
@@ -35,6 +35,7 @@ ol.inherits(ol.renderer.Layer, ol.Observable);
|
||||
/**
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @param {olx.FrameState} frameState Frame state.
|
||||
* @param {number} hitTolerance Hit tolerance in pixels.
|
||||
* @param {function(this: S, (ol.Feature|ol.render.Feature), ol.layer.Layer): T}
|
||||
* callback Feature callback.
|
||||
* @param {S} thisArg Value to use as `this` when executing `callback`.
|
||||
|
||||
@@ -100,6 +100,7 @@ ol.renderer.Map.expireIconCache_ = function(map, frameState) {
|
||||
/**
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @param {olx.FrameState} frameState FrameState.
|
||||
* @param {number} hitTolerance Hit tolerance in pixels.
|
||||
* @param {function(this: S, (ol.Feature|ol.render.Feature),
|
||||
* ol.layer.Layer): T} callback Feature callback.
|
||||
* @param {S} thisArg Value to use as `this` when executing `callback`.
|
||||
@@ -111,7 +112,7 @@ ol.renderer.Map.expireIconCache_ = function(map, frameState) {
|
||||
* @return {T|undefined} Callback result.
|
||||
* @template S,T,U
|
||||
*/
|
||||
ol.renderer.Map.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, callback, thisArg,
|
||||
ol.renderer.Map.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, callback, thisArg,
|
||||
layerFilter, thisArg2) {
|
||||
var result;
|
||||
var viewState = frameState.viewState;
|
||||
@@ -155,7 +156,7 @@ ol.renderer.Map.prototype.forEachFeatureAtCoordinate = function(coordinate, fram
|
||||
if (layer.getSource()) {
|
||||
result = layerRenderer.forEachFeatureAtCoordinate(
|
||||
layer.getSource().getWrapX() ? translatedCoordinate : coordinate,
|
||||
frameState, forEachFeatureAtCoordinate, thisArg);
|
||||
frameState, hitTolerance, forEachFeatureAtCoordinate, thisArg);
|
||||
}
|
||||
if (result) {
|
||||
return result;
|
||||
@@ -188,6 +189,7 @@ ol.renderer.Map.prototype.forEachLayerAtPixel = function(pixel, frameState, call
|
||||
/**
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @param {olx.FrameState} frameState FrameState.
|
||||
* @param {number} hitTolerance Hit tolerance in pixels.
|
||||
* @param {function(this: U, ol.layer.Layer): boolean} layerFilter Layer filter
|
||||
* function, only layers which are visible and for which this function
|
||||
* returns `true` will be tested for features. By default, all visible
|
||||
@@ -196,9 +198,9 @@ ol.renderer.Map.prototype.forEachLayerAtPixel = function(pixel, frameState, call
|
||||
* @return {boolean} Is there a feature at the given coordinate?
|
||||
* @template U
|
||||
*/
|
||||
ol.renderer.Map.prototype.hasFeatureAtCoordinate = function(coordinate, frameState, layerFilter, thisArg) {
|
||||
ol.renderer.Map.prototype.hasFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, layerFilter, thisArg) {
|
||||
var hasFeature = this.forEachFeatureAtCoordinate(
|
||||
coordinate, frameState, ol.functions.TRUE, this, layerFilter, thisArg);
|
||||
coordinate, frameState, hitTolerance, ol.functions.TRUE, this, layerFilter, thisArg);
|
||||
|
||||
return hasFeature !== undefined;
|
||||
};
|
||||
|
||||
@@ -68,14 +68,14 @@ ol.renderer.webgl.ImageLayer.prototype.createTexture_ = function(image) {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.ImageLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, callback, thisArg) {
|
||||
ol.renderer.webgl.ImageLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, callback, thisArg) {
|
||||
var layer = this.getLayer();
|
||||
var source = layer.getSource();
|
||||
var resolution = frameState.viewState.resolution;
|
||||
var rotation = frameState.viewState.rotation;
|
||||
var skippedFeatureUids = frameState.skippedFeatureUids;
|
||||
return source.forEachFeatureAtCoordinate(
|
||||
coordinate, resolution, rotation, skippedFeatureUids,
|
||||
coordinate, resolution, rotation, hitTolerance, skippedFeatureUids,
|
||||
|
||||
/**
|
||||
* @param {ol.Feature|ol.render.Feature} feature Feature.
|
||||
@@ -213,7 +213,7 @@ ol.renderer.webgl.ImageLayer.prototype.updateProjectionMatrix_ = function(canvas
|
||||
*/
|
||||
ol.renderer.webgl.ImageLayer.prototype.hasFeatureAtCoordinate = function(coordinate, frameState) {
|
||||
var hasFeature = this.forEachFeatureAtCoordinate(
|
||||
coordinate, frameState, ol.functions.TRUE, this);
|
||||
coordinate, frameState, 0, ol.functions.TRUE, this);
|
||||
return hasFeature !== undefined;
|
||||
};
|
||||
|
||||
@@ -232,7 +232,7 @@ ol.renderer.webgl.ImageLayer.prototype.forEachLayerAtPixel = function(pixel, fra
|
||||
var coordinate = ol.transform.apply(
|
||||
frameState.pixelToCoordinateTransform, pixel.slice());
|
||||
var hasFeature = this.forEachFeatureAtCoordinate(
|
||||
coordinate, frameState, ol.functions.TRUE, this);
|
||||
coordinate, frameState, 0, ol.functions.TRUE, this);
|
||||
|
||||
if (hasFeature) {
|
||||
return callback.call(thisArg, this.getLayer(), null);
|
||||
|
||||
@@ -502,7 +502,7 @@ ol.renderer.webgl.Map.prototype.renderFrame = function(frameState) {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, callback, thisArg,
|
||||
ol.renderer.webgl.Map.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, callback, thisArg,
|
||||
layerFilter, thisArg2) {
|
||||
var result;
|
||||
|
||||
@@ -522,7 +522,7 @@ ol.renderer.webgl.Map.prototype.forEachFeatureAtCoordinate = function(coordinate
|
||||
layerFilter.call(thisArg2, layer)) {
|
||||
var layerRenderer = this.getLayerRenderer(layer);
|
||||
result = layerRenderer.forEachFeatureAtCoordinate(
|
||||
coordinate, frameState, callback, thisArg);
|
||||
coordinate, frameState, hitTolerance, callback, thisArg);
|
||||
if (result) {
|
||||
return result;
|
||||
}
|
||||
@@ -535,7 +535,7 @@ ol.renderer.webgl.Map.prototype.forEachFeatureAtCoordinate = function(coordinate
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.Map.prototype.hasFeatureAtCoordinate = function(coordinate, frameState, layerFilter, thisArg) {
|
||||
ol.renderer.webgl.Map.prototype.hasFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, layerFilter, thisArg) {
|
||||
var hasFeature = false;
|
||||
|
||||
if (this.getGL().isContextLost()) {
|
||||
|
||||
@@ -106,7 +106,7 @@ ol.renderer.webgl.VectorLayer.prototype.disposeInternal = function() {
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.renderer.webgl.VectorLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, callback, thisArg) {
|
||||
ol.renderer.webgl.VectorLayer.prototype.forEachFeatureAtCoordinate = function(coordinate, frameState, hitTolerance, callback, thisArg) {
|
||||
if (!this.replayGroup_ || !this.layerState_) {
|
||||
return undefined;
|
||||
} else {
|
||||
|
||||
@@ -155,14 +155,14 @@ ol.source.ImageVector.prototype.canvasFunctionInternal_ = function(extent, resol
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.source.ImageVector.prototype.forEachFeatureAtCoordinate = function(
|
||||
coordinate, resolution, rotation, skippedFeatureUids, callback) {
|
||||
coordinate, resolution, rotation, hitTolerance, skippedFeatureUids, callback) {
|
||||
if (!this.replayGroup_) {
|
||||
return undefined;
|
||||
} else {
|
||||
/** @type {Object.<string, boolean>} */
|
||||
var features = {};
|
||||
return this.replayGroup_.forEachFeatureAtCoordinate(
|
||||
coordinate, resolution, 0, skippedFeatureUids,
|
||||
coordinate, resolution, 0, hitTolerance, skippedFeatureUids,
|
||||
/**
|
||||
* @param {ol.Feature|ol.render.Feature} feature Feature.
|
||||
* @return {?} Callback result.
|
||||
|
||||
@@ -94,6 +94,7 @@ ol.source.Source.toAttributionsArray_ = function(attributionLike) {
|
||||
* @param {ol.Coordinate} coordinate Coordinate.
|
||||
* @param {number} resolution Resolution.
|
||||
* @param {number} rotation Rotation.
|
||||
* @param {number} hitTolerance Hit tolerance in pixels.
|
||||
* @param {Object.<string, boolean>} skippedFeatureUids Skipped feature uids.
|
||||
* @param {function((ol.Feature|ol.render.Feature)): T} callback Feature
|
||||
* callback.
|
||||
|
||||
33
test/spec/ol/render/canvas/replaygroup.test.js
Normal file
33
test/spec/ol/render/canvas/replaygroup.test.js
Normal file
@@ -0,0 +1,33 @@
|
||||
goog.provide('ol.test.render.canvas.ReplayGroup');
|
||||
|
||||
goog.require('ol.render.canvas.ReplayGroup');
|
||||
|
||||
|
||||
describe('ol.render.canvas.ReplayGroup', function() {
|
||||
|
||||
describe('#getCircleArray_', function() {
|
||||
it('creates an array with a pixelated circle marked with true', function() {
|
||||
var radius = 10;
|
||||
var minRadiusSq = Math.pow(radius - Math.SQRT2, 2);
|
||||
var maxRadiusSq = Math.pow(radius + Math.SQRT2, 2);
|
||||
var circleArray = ol.render.canvas.ReplayGroup.getCircleArray_(radius);
|
||||
var size = radius * 2 + 1;
|
||||
expect(circleArray.length).to.be(size);
|
||||
|
||||
for (var i = 0; i < size; i++) {
|
||||
expect(circleArray[i].length).to.be(size);
|
||||
for (var j = 0; j < size; j++) {
|
||||
var dx = Math.abs(radius - i);
|
||||
var dy = Math.abs(radius - j);
|
||||
var distanceSq = Math.pow(dx, 2) + Math.pow(dy, 2);
|
||||
if (circleArray[i][j] === true) {
|
||||
expect(distanceSq).to.be.within(0, maxRadiusSq);
|
||||
} else {
|
||||
expect(distanceSq).to.be.within(minRadiusSq, Infinity);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
});
|
||||
@@ -30,7 +30,7 @@ describe('ol.renderer.canvas.Map', function() {
|
||||
|
||||
var layer, map, target;
|
||||
|
||||
beforeEach(function() {
|
||||
beforeEach(function(done) {
|
||||
target = document.createElement('div');
|
||||
target.style.width = '100px';
|
||||
target.style.height = '100px';
|
||||
@@ -42,6 +42,14 @@ describe('ol.renderer.canvas.Map', function() {
|
||||
zoom: 0
|
||||
})
|
||||
});
|
||||
|
||||
// 1 x 1 pixel black icon
|
||||
var img = document.createElement('img');
|
||||
img.onload = function() {
|
||||
done();
|
||||
};
|
||||
img.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAAAAAA6fptVAAAACklEQVR4nGNiAAAABgADNjd8qAAAAABJRU5ErkJggg==';
|
||||
|
||||
layer = new ol.layer.Vector({
|
||||
source: new ol.source.Vector({
|
||||
features: [
|
||||
@@ -49,6 +57,12 @@ describe('ol.renderer.canvas.Map', function() {
|
||||
geometry: new ol.geom.Point([0, 0])
|
||||
})
|
||||
]
|
||||
}),
|
||||
style: new ol.style.Style({
|
||||
image: new ol.style.Icon({
|
||||
img : img,
|
||||
imgSize: [1, 1]
|
||||
})
|
||||
})
|
||||
});
|
||||
});
|
||||
@@ -97,10 +111,11 @@ describe('ol.renderer.canvas.Map', function() {
|
||||
map.addLayer(layer);
|
||||
map.renderSync();
|
||||
var cb = sinon.spy();
|
||||
map.forEachFeatureAtPixel(map.getPixelFromCoordinate([0, 0]), cb, null,
|
||||
function() {
|
||||
return false;
|
||||
});
|
||||
map.forEachFeatureAtPixel(map.getPixelFromCoordinate([0, 0]), cb, {
|
||||
layerFilter: function() {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
expect(cb).to.not.be.called();
|
||||
});
|
||||
|
||||
@@ -113,6 +128,39 @@ describe('ol.renderer.canvas.Map', function() {
|
||||
}).to.not.throwException();
|
||||
});
|
||||
|
||||
it('calls callback for clicks inside of the hitTolerance', function() {
|
||||
map.addLayer(layer);
|
||||
map.renderSync();
|
||||
var cb1 = sinon.spy();
|
||||
var cb2 = sinon.spy();
|
||||
|
||||
var pixel = map.getPixelFromCoordinate([0, 0]);
|
||||
|
||||
var pixelsInside = [
|
||||
[pixel[0] + 9, pixel[1]],
|
||||
[pixel[0] - 9, pixel[1]],
|
||||
[pixel[0], pixel[1] + 9],
|
||||
[pixel[0], pixel[1] - 9]
|
||||
];
|
||||
|
||||
var pixelsOutside = [
|
||||
[pixel[0] + 9, pixel[1] + 9],
|
||||
[pixel[0] - 9, pixel[1] + 9],
|
||||
[pixel[0] + 9, pixel[1] - 9],
|
||||
[pixel[0] - 9, pixel[1] - 9]
|
||||
];
|
||||
|
||||
for (var i = 0; i < 4; i++) {
|
||||
map.forEachFeatureAtPixel(pixelsInside[i], cb1, {hitTolerance:10});
|
||||
}
|
||||
expect(cb1.callCount).to.be(4);
|
||||
expect(cb1.firstCall.args[1]).to.be(layer);
|
||||
|
||||
for (var j = 0; j < 4; j++) {
|
||||
map.forEachFeatureAtPixel(pixelsOutside[j], cb2, {hitTolerance:10});
|
||||
}
|
||||
expect(cb2).not.to.be.called();
|
||||
});
|
||||
});
|
||||
|
||||
describe('#renderFrame()', function() {
|
||||
|
||||
@@ -79,7 +79,7 @@ describe('ol.renderer.canvas.VectorLayer', function() {
|
||||
var replayGroup = {};
|
||||
renderer.replayGroup_ = replayGroup;
|
||||
replayGroup.forEachFeatureAtCoordinate = function(coordinate,
|
||||
resolution, rotation, skippedFeaturesUids, callback) {
|
||||
resolution, rotation, hitTolerance, skippedFeaturesUids, callback) {
|
||||
var feature = new ol.Feature();
|
||||
callback(feature);
|
||||
callback(feature);
|
||||
@@ -99,7 +99,7 @@ describe('ol.renderer.canvas.VectorLayer', function() {
|
||||
};
|
||||
frameState.layerStates[ol.getUid(layer)] = {};
|
||||
renderer.forEachFeatureAtCoordinate(
|
||||
coordinate, frameState, spy, undefined);
|
||||
coordinate, frameState, 0, spy, undefined);
|
||||
expect(spy.callCount).to.be(1);
|
||||
expect(spy.getCall(0).args[1]).to.equal(layer);
|
||||
});
|
||||
|
||||
@@ -169,7 +169,7 @@ describe('ol.renderer.canvas.VectorTileLayer', function() {
|
||||
});
|
||||
renderer = new ol.renderer.canvas.VectorTileLayer(layer);
|
||||
replayGroup.forEachFeatureAtCoordinate = function(coordinate,
|
||||
resolution, rotation, skippedFeaturesUids, callback) {
|
||||
resolution, rotation, hitTolerance, skippedFeaturesUids, callback) {
|
||||
var feature = new ol.Feature();
|
||||
callback(feature);
|
||||
callback(feature);
|
||||
@@ -190,7 +190,7 @@ describe('ol.renderer.canvas.VectorTileLayer', function() {
|
||||
frameState.layerStates[ol.getUid(layer)] = {};
|
||||
renderer.renderedTiles = [new TileClass([0, 0, -1])];
|
||||
renderer.forEachFeatureAtCoordinate(
|
||||
coordinate, frameState, spy, undefined);
|
||||
coordinate, frameState, 0, spy, undefined);
|
||||
expect(spy.callCount).to.be(1);
|
||||
expect(spy.getCall(0).args[1]).to.equal(layer);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user