Search code examples
javascriptopenlayersopenlayers-3

OpenLayers: Clicking close (but not exactly) on a vector to get vector features


I have an Open Street Map and some vectors (lines) that appear over the roads. When I click on the vector I am able to get the features of that vector, however I can only do so by clicking exactly on the pixels of the vector. Is there a way I can click 'near' the vector (maybe off by a few pixels) to get the information so I don't have to be as precise?

Code:

This is what I am currently using to get the features when I click on a vector:

var displayFeatureInfo  = function (pixel, coordinate) {
            var features = [];
            map.forEachFeatureAtPixel(pixel, function (feature, layer) {
                features.push(feature); // Pushes each feature found into the array
            });

            if (features.length > 0) {   // If there are one or more features
                $("#popup").html('<object data=' + "http://URLToLoadDataFrom '/>'); // Load the data using jQuery
                popup.setPositioning('top-left');
                popup.setPosition(coordinate);
                container.style.display = 'block';
            } else {
                container.style.display = 'none';
            }                          

        };

        map.on('click', function (evt) {
            var coordinate = evt.coordinate;
            displayFeatureInfo(evt.pixel, coordinate);    
        });

Thanks in advance.


Solution

  • You can build an extent out of the supplied pixel and base your feature selection using the extent instead of a single point. Thought, that means you have to use vector.getSource().forEachFeatureIntersectingExtent method instead of map.forEachFeatureAtPixel.

    Check this (fiddle here):

    var displayFeatureInfo  = function (pixel, coordinate) {
                var features = [];
                //this is the offset in pixels. Adjust it to fit your needs
                var pixelOffSet = 5; 
                var pixelWithOffsetMin = [pixel[0]-pixelOffSet,pixel[1]+pixelOffSet];
                var pixelWithOffsetMax = [pixel[0]+pixelOffSet,pixel[1]-pixelOffSet];
                var XYMin =map.getCoordinateFromPixel(pixelWithOffsetMin)
                var XYMax =map.getCoordinateFromPixel(pixelWithOffsetMax)
                var extent = XYMax.concat(XYMin);
                var extentFeat= new ol.Feature(new ol.geom.Polygon([[
                [extent[0],extent[1]],
                [extent[0],extent[3]],
                [extent[2],extent[3]],
                [extent[2],extent[1]],
                [extent[0],extent[1]]
                ]]));   
    
                vector.getSource().forEachFeatureIntersectingExtent(extentFeat.getGeometry().getExtent(), 
                function (feature) {
                    features.push(feature); // Pushes each feature found into the array
                });
    
                if (features.length > 0) {   // If there are one or more features
                    console.log("features found on offset clicked",features)
                   // container.style.display = 'block';
                } else {
                  console.log("no features on offset click")
                }                          
    
            };
    
            map.on('click', function (evt) {
                var coordinate = evt.coordinate;
                displayFeatureInfo(evt.pixel, coordinate);    
            });