Hi everyone,
I have a problem using HTML overlays with CesiumJS on mobile devices.
My problem is that if I zoom on the map or translate it with a gesture, the overlays block the touch events addressed to the map (obviously having a z-index bigger than the map).
Specifically, if I do a pinch having a finger on the overlay and the other on the map, I’m unable to zoom.
Since I’m new to Cesium, I don’t know if the overlay is the best option, but I need to show multiple images with a border on the map (like a profile picture) and, when I tap on one of them, it will open the relative infos with a modal.
I would achieve an effect like Google maps in which I can interact with the map but also open a pin tapping on it.
Hi Omar,
Thank you for your answer.
Yes I’m using custom html overlays as in this Sandcastle
In this, if you put the mouse on the overlay and try to zoom on the map using the mouse wheel, it simply does nothing.
I tried also your suggested solution but that CSS rule will disable all pointer/touch events. So I’m unable to click on the overlay and open its infos.
As I said, I would achive a Maps like experience: zoom doing a pinch (even if during the gesture I’m touching an overlay) and open the overlay’s infos tapping on it.
Basically the overlays should only allow clicks/taps on them. Other events should be ignored and “passed” to the map.
If I put “pointer-events: none;” in the img tag, all events are ignored and the alert will not appear if the overlay is clicked.
If I put “pointer-events: auto;” the alert will appear but I’m in the same situation as the original code of the Sandcastle (can’t drag or zoom if on the overlay).
Is there some JS workaround?
The problem is that if I have multiple overlays on the globe, it’s difficult to drag or zoom the map because you have to find “empty” places to start the action.
I think the typical solution here is if the buttons/overlays are taking up too much of the screen is to put them in a collapsible panel, and have them generally as a different color so it’s clear they’re not part of the map (for example: https://nsw.digitaltwin.terria.io/).
Otherwise, you may be able to do this by having all pointer events turned off on your overlays, and having the canvas catch any clicks, figure out if the mouse was over a button, and then initiate the right action. Doing so you’ll lose a lot of built-in browser functionality like hover highlights etc.
Alternatively, you could enable all point events on the HTML overlays, add event listeners for click and drag, and scroll etc, and programmatically trigger the right action on the Cesium map when those occur. This is again not very trivial and I don’t have a ready example for this.
If you are comfortable sharing I’d be curious to see what your layout looks like with your overlays. I don’t think I’ve seen anyone run into this particular issue before so it’d be interesting to see.
Hi, I can’t share the real layout but I can share another Sandcastle (very very basic) that gives a good idea of it. Don’t know why I can’t share the link (it says you can’t share a link to that host).
However if you paste this code in the standard overlay sandcastle:
var viewer = new Cesium.Viewer("cesiumContainer");
var scratch = new Cesium.Cartesian2();
var postsInGlobe = document.getElementsByClassName('htmlOverlay');
viewer.scene.preRender.addEventListener(function () {
var position = Cesium.Cartesian3.fromDegrees(-75.59777, 40.03883);
var canvasPosition = viewer.scene.cartesianToCanvasCoordinates(
position,
scratch
);
if (Cesium.defined(canvasPosition)) {
postsInGlobe[0].style.top = canvasPosition.y + "px";
postsInGlobe[0].style.left = canvasPosition.x + "px";
}
});
viewer.scene.preRender.addEventListener(function () {
var position = Cesium.Cartesian3.fromDegrees(-85.59777, 40.03883);
var canvasPosition = viewer.scene.cartesianToCanvasCoordinates(
position,
scratch
);
if (Cesium.defined(canvasPosition)) {
postsInGlobe[1].style.top = canvasPosition.y + "px";
postsInGlobe[1].style.left = canvasPosition.x + "px";
}
});
viewer.scene.preRender.addEventListener(function () {
var position = Cesium.Cartesian3.fromDegrees(-76.59777, 48.03883);
var canvasPosition = viewer.scene.cartesianToCanvasCoordinates(
position,
scratch
);
if (Cesium.defined(canvasPosition)) {
postsInGlobe[2].style.top = canvasPosition.y + "px";
postsInGlobe[2].style.left = canvasPosition.x + "px";
}
});
You can see somithing similar to what I have.
If you try to interact with it with a touchscreen (the mouse is also ok), you are disturbed on zooming and rotating the view because of the overlays. Imagine 10 or 20 overlays almost filling the viewport. You don’t have space to zoom or rotate the map.
Is it possible with billboards to open an html modal with the clicked element’s details?
Instead of doing it on mouse over, you can do it on click, and if it picks a specific billboard, you can trigger the action you’d like with JavaScript.
hello , some solution for hmtl overlays with this problem ?
i’m in the same situation , have multipls hmtl overlays , and i cant wheel , while cursor is on some of the overlays