Edit

Hit Tolerance

hitTolerance1

Try to click the line in the map.
  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 Feature from 'ol/Feature.js';
import LineString from 'ol/geom/LineString.js';
import Map from 'ol/Map.js';
import View from 'ol/View.js';
import {OSM, Vector as VectorSource} from 'ol/source.js';
import {Stroke, Style} from 'ol/style.js';
import {Tile as TileLayer, Vector as VectorLayer} from 'ol/layer.js';

const raster = new TileLayer({
  source: new OSM(),
});

const style = new Style({
  stroke: new Stroke({
    color: 'black',
    width: 1,
  }),
});

const feature = new Feature(
  new LineString([
    [-4000000, 0],
    [4000000, 0],
  ]),
);

const vector = new VectorLayer({
  source: new VectorSource({
    features: [feature],
  }),
  style: style,
});

const map = new Map({
  layers: [raster, vector],
  target: 'map',
  view: new View({
    center: [0, 0],
    zoom: 2,
  }),
});

let hitTolerance;

const statusElement = document.getElementById('status');

map.on('singleclick', function (e) {
  let 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();
});

const selectHitToleranceElement = document.getElementById('hitTolerance');
const circleCanvas = document.getElementById('circle');

const changeHitTolerance = function () {
  hitTolerance = parseInt(selectHitToleranceElement.value, 10);

  const size = 2 * hitTolerance + 2;
  circleCanvas.width = size;
  circleCanvas.height = size;
  const 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>
    <meta charset="UTF-8">
    <title>Hit Tolerance</title>
    <link rel="stylesheet" href="node_modules/ol/ol.css">
    <style>
      .map {
        width: 100%;
        height: 400px;
      }
    </style>
  </head>
  <body>
    <div id="map" class="map"></div>
    <span id="status">Try to click the line in the map.</span>
    <form>
      <label for="hitTolerance">Hit tolerance for selecting features: &nbsp;</label>
      <select id="hitTolerance">
        <option value="0" selected>0 Pixels</option>
        <option value="5">5 Pixels</option>
        <option value="10">10 Pixels</option>
      </select>
      &nbsp; Area: &nbsp;
      <canvas id="circle" style="vertical-align: middle"></canvas>
    </form>

    <script type="module" src="main.js"></script>
  </body>
</html>
package.json
{
  "name": "hit-tolerance",
  "dependencies": {
    "ol": "9.1.0"
  },
  "devDependencies": {
    "vite": "^3.2.3"
  },
  "scripts": {
    "start": "vite",
    "build": "vite build"
  }
}