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

Link pointer when hovering over clickable feature in map. #1292

Merged
merged 3 commits into from
Sep 2, 2021
Merged
Show file tree
Hide file tree
Changes from all 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
23 changes: 23 additions & 0 deletions src/featureinfo.js
Original file line number Diff line number Diff line change
Expand Up @@ -423,6 +423,29 @@ const Featureinfo = function Featureinfo(options = {}) {
setActive(false);
}
});

// Change mouse pointer when hovering over a clickable feature
if (viewer.getViewerOptions().featureinfoOptions.changePointerOnHover) {
let pointerActive = true;
document.addEventListener('enableInteraction', evt => {
pointerActive = evt.detail.interaction !== 'editor';
// Avoid getting stuck in pointer mode if user manages to enable editing while having pointer over a clickable feature.
// If the user manages to disable editing while standing on a clickable feature, it will remain arrow until moved. (Sorry)
map.getViewport().style.cursor = '';
});

// 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' : '';
});
}
},
render
});
Expand Down
12 changes: 12 additions & 0 deletions src/layer.js
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,18 @@ const Layer = function Layer(optOptions, viewer) {
layerOptions.className = layerOptions.cls || `o-layer-${layerOptions.name}`;
}

// changePointerOnHover requires that non queryable layers are not drawn on the same canvas as queryable layers.
// OL will merge layers to the same canvas if they have the same class and some other reconcilable properties.
// Note that the merge preserves layer ordering, so if a layer can not use same canvas as previous layer, a new
// canvas will be created, so keep layers with same properties together.
// Make sure that queryable layers get a class name to avoid merging with non queryable layers.
// A unique class would be best, but produces a new canvas for each layer, which could affect the
// performance.
// If user has configured a className then keep it and let the user take the consequences if they mix queryable and non queryable layers.
if (viewer.getViewerOptions().featureinfoOptions.changePointerOnHover && layerOptions.queryable && !layerOptions.className) {
layerOptions.className = 'o-layer-queryable';
}

if (layerOptions.type) {
const layer = type[layerOptions.type](layerOptions, viewer);
layer.once('postrender', onChangeVisible);
Expand Down