Example using the hitTolerance parameter.
By default, the map.forEachFeatureAtPixel() function only considers features that are directly under the provided pixel. This can make it difficult to interact with features on touch devices. To consider features within some distance of the provided pixel, use the hitTolerance option. For example, map.forEachFeatureAtPixel(pixel, callback, {hitTolerance: 3}) will call the callback with all features that are within three pixels of the provided pixel.
<!DOCTYPE html>
<html lang="en">
<head>
<title>Hit Tolerance</title>
<!-- The line below is only needed for old environments like Internet Explorer and Android 4.x -->
<script src="https://cdn.polyfill.io/v2/polyfill.min.js?features=requestAnimationFrame,Element.prototype.classList,URL"></script>
<style>
.map {
width: 100%;
height:400px;
}
</style>
</head>
<body>
<div id="map" class="map"></div>
<form class="form-inline">
<span id="status"> No feature got hit.</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>
<br />
Area: <canvas id="circle" style="vertical-align: middle"/>
</form>
<script src="index.js"></script>
</body>
</html>
import 'ol/ol.css';
import Map from 'ol/Map';
import View from 'ol/View';
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer';
import {OSM, Vector as VectorSource} from 'ol/source';
import Feature from 'ol/Feature';
import LineString from 'ol/geom/LineString';
import {Stroke, Style} from 'ol/style';
var raster = new TileLayer({
source: new OSM()
});
var style = new Style({
stroke: new Stroke({
color: 'black',
width: 1
})
});
var feature = new Feature(new LineString([[-4000000, 0], [4000000, 0]]));
var vector = new VectorLayer({
source: new VectorSource({
features: [feature]
}),
style: style
});
var map = new Map({
layers: [raster, vector],
target: 'map',
view: new View({
center: [0, 0],
zoom: 2
})
});
var hitTolerance;
var statusElement = document.getElementById('status');
map.on('singleclick', function(e) {
var hit = false;
map.forEachFeatureAtPixel(e.pixel, function() {
hit = true;
}, {
hitTolerance: hitTolerance
});
if (hit) {
style.getStroke().setColor('green');
statusElement.innerHTML = ' A feature got hit!';
} else {
style.getStroke().setColor('black');
statusElement.innerHTML = ' No feature got hit.';
}
feature.changed();
});
var selectHitToleranceElement = document.getElementById('hitTolerance');
var circleCanvas = document.getElementById('circle');
var changeHitTolerance = function() {
hitTolerance = parseInt(selectHitToleranceElement.value, 10);
var size = 2 * hitTolerance + 2;
circleCanvas.width = size;
circleCanvas.height = size;
var ctx = circleCanvas.getContext('2d');
ctx.clearRect(0, 0, size, size);
ctx.beginPath();
ctx.arc(hitTolerance + 1, hitTolerance + 1, hitTolerance + 0.5, 0, 2 * Math.PI);
ctx.fill();
ctx.stroke();
};
selectHitToleranceElement.onchange = changeHitTolerance;
changeHitTolerance();
{
"name": "hit-tolerance",
"dependencies": {
"ol": "6.1.1"
},
"devDependencies": {
"parcel": "1.11.0"
},
"scripts": {
"start": "parcel index.html",
"build": "parcel build --experimental-scope-hoisting --public-url . index.html"
}
}