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

Cesium captures mouse click events #4126

Closed
hpinkos opened this issue Jul 15, 2016 · 8 comments
Closed

Cesium captures mouse click events #4126

hpinkos opened this issue Jul 15, 2016 · 8 comments

Comments

@hpinkos
Copy link
Contributor

hpinkos commented Jul 15, 2016

Clicking on the Cesium viewer prevents focus being removed from other page elements. In this example, I added an input textbox that turns red when it has focus and white when it loses it. If you click in the textbox to focus, then click in Cesium, you'll see the textbox stays red. However if you click elsewhere in the sandcastle app the textbox correctly loses focus. I think this is happening because Cesium is capturing the click event and preventing any default behavior, but I'm not 100% sure. I know this isn't the default behavior for a canvas though, I checked that with a tiny JSFiddle demo

This gets frustrating when an Cesium has form elements have behavior that relies on focus and clicking away from the element and onto the canvas doesn't produce the expected behavior.

<style>
    @import url(../templates/bucket.css);
    .myDiv{
        position: absolute;
        top: 0;
        left: 0;
        height: 20px;
        width: 200px;
    }
    .myDiv input:focus {
        background-color: red;
    }
</style>
<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div class="myDiv"><input type="text"></div>
<div id="toolbar"></div>
@emackey
Copy link
Contributor

emackey commented Jul 18, 2016

This is a tricky issue because the prevention of default behavior is quite intentional. If we don't prevent default behavior, actions like panning the globe would have side effects of drag-selecting DOM elements in the vicinity of the canvas at the same time. If memory serves, the Geocoder widget has a better solution, I think it may be listening to the canvas (or the screenspaceeventhandler) and giving up its own focus voluntarily. It's worth double-checking what the Geocoder actually does, but I bet mimicking its behavior will yield better UX than enabling default event processing on the canvas.

@emackey
Copy link
Contributor

emackey commented Feb 8, 2017

Here's my recommended workaround for this. Use this JS code in the same Sandcastle demo as @hpinkos HTML template above, to see the effects:

var viewer = new Cesium.Viewer('cesiumContainer');

viewer.scene.canvas.setAttribute('tabIndex', 1);

viewer.screenSpaceEventHandler.setInputAction(function() {
    viewer.scene.canvas.focus();
}, Cesium.ScreenSpaceEventType.LEFT_DOWN);

What happens here is that we set the Cesium canvas itself to have a tabIndex value, allowing it to receive the focus. Then, a pointer-event-friendly click handler is registered that manually assigns the focus to the canvas when clicked. This doesn't break the geocoder or other widgets because we assigned to the canvas itself, not the container div.

The tabIndex is an app-global number, so I think this workaround needs to be app code, not a Cesium fix (or we would need to expose a way to set the tab index value on the viewer).

The reason this workaround is needed is because we intentionally prevent the default behavior for left-drags, otherwise the credit text and/or widgets would get the blue selection highlight every time you pan the globe.

@emackey
Copy link
Contributor

emackey commented Feb 8, 2017

Here's a link to the completed workaround, with some restyling:

https://cesiumjs.org/Cesium/Build/Apps/Sandcastle/?src=Hello%20World.html&label=Showcases&gist=38dcfe80a26c8995d9f4290da10f441d

I recommend we close this, unless people think the workaround belongs in Cesium.

@hpinkos
Copy link
Contributor Author

hpinkos commented Feb 8, 2017

Thanks @emackey

@hpinkos hpinkos closed this as completed Feb 8, 2017
@hungdn580
Copy link

hungdn580 commented Sep 17, 2018

sorry, link is no longer active, can you please post it again?

@hungdn580
Copy link

@emackey ema

@emackey
Copy link
Contributor

emackey commented Sep 17, 2018

Apologies for the broken link. Try this: Sandcastle Demo

CSS is here:

<style>
    @import url(../templates/bucket.css);
    .myDiv{
        position: absolute;
        top: 8px;
        left: 10px;
        height: 30px;
        width: 300px;
    }
    .myDiv input {
        font-size: 16px;
        padding: 2px;
    }
    .myDiv input:focus {
        background-color: yellow;
    }
</style>

HTML:

<div id="cesiumContainer" class="fullSize"></div>
<div id="loadingOverlay"><h1>Loading...</h1></div>
<div class="myDiv"><input type="text" placeholder="Text entry"></div>
<div id="toolbar"></div>

JS:

var viewer = new Cesium.Viewer('cesiumContainer');

viewer.scene.canvas.setAttribute('tabIndex', 1);

viewer.screenSpaceEventHandler.setInputAction(function(e) {
    viewer.scene.canvas.focus();
}, Cesium.ScreenSpaceEventType.LEFT_DOWN);

@hungdn580
Copy link

Thanks @emackey
But can I ask you one more question relative to mouse event in cesium.

In function setInputAction I have code something like this

// Pick a new feature
        var pickedFeature = viewer.scene.pick(movement.position);
        if (!Cesium.defined(pickedFeature)) {
            clickHandler(movement);
            return;
        }
}

code above can run ok but when I get getProperty from pickedFeature

selectedEntity.description = 'Loading <div class="cesium-infoBox-loading"></div>';
        viewer.selectedEntity = selectedEntity;
        selectedEntity.description = '<table class="cesium-infoBox-defaultTable"><tbody>' +
                                     '<tr><th>BIN</th><td>' + pickedFeature.getProperty('BIN') + '</td></tr>' +
                                     '<tr><th>DOITT ID</th><td>' + pickedFeature.getProperty('DOITT_ID') + '</td></tr>' +
                                     '<tr><th>SOURCE ID</th><td>' + pickedFeature.getProperty('SOURCE_ID') + '</td></tr>' +
                                     '<tr><th>Longitude</th><td>' + pickedFeature.getProperty('longitude') + '</td></tr>' +
                                     '<tr><th>Latitude</th><td>' + pickedFeature.getProperty('latitude') + '</td></tr>' +
                                     '<tr><th>Height</th><td>' + pickedFeature.getProperty('height') + '</td></tr>' +
                                     '<tr><th>Terrain Height (Ellipsoid)</th><td>' + pickedFeature.getProperty('TerrainHeight') + '</td></tr>' +
                                     '</tbody></table>';

I always get errors "Uncaught TypeError: pickedFeature.getProperty is not a function"!
Can you please guide me this issues, Thank you very much!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants