Edit

Hit Tolerance

hitTolerance1

 No feature got hit.

Area:  

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.

main.js
import 'ol/ol.css';
import Feature from 'ol/Feature';
import LineString from 'ol/geom/LineString';
import Map from 'ol/Map';
import View from 'ol/View';
import {OSM, Vector as VectorSource} from 'ol/source';
import {Stroke, Style} from 'ol/style';
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer';

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();
index.html
<!DOCTYPE html>
<html lang="en">
  <head>
    <title>Hit Tolerance</title>
    <!-- Pointer events polyfill for old browsers, see https://caniuse.com/#feat=pointer -->
    <script src="https://unpkg.com/elm-pep"></script>
    <style>
      .map {
        width: 100%;
        height:400px;
      }
    </style>
  </head>
  <body>
    <div id="map" class="map"></div>
    <form class="form-inline">
      <span id="status">&nbsp;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: &nbsp;<canvas id="circle" style="vertical-align: middle"/>
    </form>
    <script src="main.js"></script>
  </body>
</html>
package.json
{
  "name": "hit-tolerance",
  "dependencies": {
    "ol": "6.4.3"
  },
  "devDependencies": {
    "parcel": "1.11.0"
  },
  "scripts": {
    "start": "parcel index.html",
    "build": "parcel build --experimental-scope-hoisting --public-url . index.html"
  }
}