Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Ol v6141 #1513

Merged
merged 7 commits into from
Jun 1, 2022
Merged
Show file tree
Hide file tree
Changes from 6 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
116 changes: 48 additions & 68 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

4 changes: 2 additions & 2 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -39,9 +39,9 @@
"downloadjs": "^1.4.7",
"elm-pep": "^1.0.6",
"html2canvas": "^1.4.0",
"ol-mapbox-style": "6.8.3",
"ol-mapbox-style": "7.1.0",
"jspdf": "^2.5.0",
"ol": "^6.12.0",
"ol": "^6.14.1",
"pepjs": "^0.5.3",
"proj4": "^2.7.5"
},
Expand Down
26 changes: 19 additions & 7 deletions src/featureinfo.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
import Overlay from 'ol/Overlay';
import TileLayer from 'ol/layer/Tile';
import OGlide from './oglide';
import { Component, Modal } from './ui';
import Popup from './popup';
Expand Down Expand Up @@ -662,13 +663,24 @@ const Featureinfo = function Featureinfo(options = {}) {
// Check if there is a clickable feature when mouse is moved.
map.on('pointermove', evt => {
if (!pointerActive || evt.dragging) return;
// Just check if there is a pixel here. Pretty annoying on hatched symbols or hollow areas.
// Note that forEachLayerAtPixel actually only checks if there is a pixel on the canvas where the layer resides,
// so non queryable layers must not share canvas with queryable layers, otherwise there will be false positives.
// When a pixel is found on the canvas, the callback is called with all layers added to that canvas as it does not know which layer actually draw a pixel there. But we don't care which
// layer was hit to change the pointer.
// Hit tolerence seems to be ignored. It would probably look funny anyway.
map.getViewport().style.cursor = map.forEachLayerAtPixel(evt.pixel, () => true, { layerFilter: (l) => l.get('queryable') }) ? 'pointer' : '';
let cursor = '';
const features = map.getFeaturesAtPixel(evt.pixel, { layerFilter(layer) {
return layer.get('queryable');
}
});
if (features.length > 0) {
cursor = 'pointer';
} else {
const layers = viewer.getQueryableLayers().filter(layer => layer instanceof TileLayer);
for (let i = 0; i < layers.length; i += 1) {
const layer = layers[i];
if (layer.getData(evt.pixel) instanceof Uint8ClampedArray && layer.getData(evt.pixel)[3] > 0) {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If renderMode is "image" for a WMS layer test will fail. Don't know why anyone would not tile an image layer, but it should test for ImageLayer as well and possibly test for BaseTileLayer instead of TileLayer. Apparently getData actually exists on all layers, but documentation states it only exist on ImageLayer and BaseTileLayer so checking for its existance is useless.

cursor = 'pointer';
break;
}
}
}
map.getViewport().style.cursor = cursor;
});
}
},
Expand Down
70 changes: 7 additions & 63 deletions src/getfeatureinfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -135,31 +135,6 @@ function getAGSIdentifyUrl({ layer, coordinate }, viewer) {
}).catch(error => console.error(error));
}

function isTainted({
pixel,
layerFilter,
map
}) {
try {
if (layerFilter) {
map.forEachLayerAtPixel(pixel, (layer) => layerFilter === layer);
}

return false;
} catch (e) {
console.error(e);
return true;
}
}

function layerAtPixel({
pixel,
matchLayer,
map
}) {
map.forEachLayerAtPixel(pixel, (layer) => matchLayer === layer);
}

function getGetFeatureInfoRequest({ layer, coordinate }, viewer) {
const layerType = layer.get('type');
const obj = {};
Expand Down Expand Up @@ -201,48 +176,17 @@ function getGetFeatureInfoRequest({ layer, coordinate }, viewer) {

function getFeatureInfoRequests({
coordinate,
layers,
map,
pixel
}, viewer) {
const requests = [];
// Check for support of crossOrigin in image, absent in IE 8 and 9
if ('crossOrigin' in new (Image)()) {
map.forEachLayerAtPixel(pixel, (layer) => {
if (layer.get('queryable')) {
const item = getGetFeatureInfoRequest({ layer, coordinate }, viewer);
if (item) {
requests.push(item);
}
viewer.getQueryableLayers().forEach(layer => {
if (layer.getData(pixel) instanceof Uint8ClampedArray && layer.getData(pixel)[3] > 0) {
const item = getGetFeatureInfoRequest({ layer, coordinate }, viewer);
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Little risky here. getData exists on all layer types, but is only documented on ImageLayer and BaseTileLayer. Calling it on a feature layer is harmless now (it returns null), but as it is not documented it could break.

Also calling getData two times is painful on my eyes, but it will not have any greater impact on performance.

if (item) {
requests.push(item);
}
});
} else if (isTainted({ map, pixel })) { // If canvas is tainted
layers.forEach((layer) => {
if (layer.get('queryable')) {
// If layer is tainted, then create request for layer
if (isTainted({ pixel, layer, map })) {
const item = getGetFeatureInfoRequest({ layer, coordinate }, viewer);
if (item) {
requests.push(item);
}
} else if (layerAtPixel({ pixel, layer, map })) { // If layer is not tainted, test if layer hit at pixel
const item = getGetFeatureInfoRequest({ layer, coordinate }, viewer);
if (item) {
requests.push(item);
}
}
}
});
} else { // If crossOrigin is not supported and canvas not tainted
map.forEachLayerAtPixel(pixel, (layer) => {
if (layer.get('queryable') === true) {
const item = getGetFeatureInfoRequest({ layer, coordinate }, viewer);
if (item) {
requests.push(item);
}
}
});
}
}
});
return requests;
}

Expand Down
Loading