For accessibility I'm attempting to allow arrow keys to control the camera orbit of my model viewer the moment the poster is dismissed. So far it seems that I'm able to control the camera with the arrow keys, but only if I interact with the model-viewer a second time (i.e. I click to dismiss the poster, then can't manipulate the camera until I click the 3D model at least once). This is bad form for accessibility.
Is there a way to force model viewer to accept keyboard input without needing to click/touch the 3D model at least once? So far I've tried:
- Using the
focus();
function on my model-viewer element, on my.userInput
div within it, and the canvas element within that - Setting the tab indexes of each of these to 1 with no success
- Using
delegateFocus
on my elements - Using the
enableInteraction();
function native to model-viewer - Adding an event listener when the poster is dismissed, via
this.addEventListener('keydown', this[$modelViewer].value?.onKeyDown);
I've verified that these elements are being manipulated/appended in the correct way, so it appears using focus and tab indexes isn't what allows model-viewer to take keyboard input in the first place.
How can I force model-viewer to accept keyboard input the moment the poster is dismissed and the 3D model is loaded?
CodePudding user response:
You should be able to call .focus()
on your .userInput
div, the tricky thing is that <model-viewer>
creates a Shadow DOM. The purpose of a shadow DOM is to encapsulate its child components, so you can't just get the element by class as you would in a regular DOM.
Instead, I had to first access the shadowRoot
, then look for the right <div>
inside. For example, I was able to use this on https://modelviewer.dev/, it focuses the .userInput
div whenever you click anywhere on the outer document. It uses some selection trickery that you might need to modify for your own use case:
window.addEventListener("click", (evt) => {
console.log("Focusing...");
document.getElementsByTagName("model-viewer")[0].shadowRoot.children[1].getElementsByClassName("userInput")[0].focus();
});
I presume since you have full control of your <model-viewer>
, you might be able to use this focusing approach on the load
event.
Update:
I just read that you want to give it keyboard focus upon clicking to dismiss the poster, so you might be able to use that "click"
event instead of the load event.