AR-js-org / AR.js

Image tracking, Location Based AR, Marker tracking. All on the Web.
MIT License
5.3k stars 909 forks source link

"click" events are not emitted on Android when scene is loaded dynamically #595

Open im-a-rocketman opened 4 months ago

im-a-rocketman commented 4 months ago

Do you want to request a feature or report a bug? Bug

Our application uses the following approach to dynamically load an embedded scene into a DIV element on the page.

AFRAME.registerComponent('notify-loaded', {
    init: function () {
        handleSceneLoaded()
    }
})

function loadScene() {
    const containerNode = document.getElementById("scene-container")
    containerNode.innerHTML = `
    <a-scene notify-loaded embedded loading-screen="dotsColor: #cc00b4; backgroundColor: black" vr-mode-ui="enabled: false" arjs="sourceType: webcam; videoTexture: true; debugUIEnabled: false" renderer="antialias: true; alpha: true" cursor="fuse: false; rayOrigin: mouse" raycaster="near: 0; far:10000">
        <a-assets>
            <img id="textback" src="./pins/pill_1024.png" />
            <img id="groundglow" src="./pins/groundglow.png" />
            <img id="rodglow" src="./pins/rod.png" />
        </a-assets>
        <a-camera gps-new-camera="gpsMinDistance: 0; initialPositionAsOrigin: true" arjs-device-orientation-controls="smoothingFactor: 0.99" far="5000" near="0.1"></a-camera>
    </a-scene>
    `
}

function handleSceneLoaded() {
    // Do additional stuff like loading objects into the scene here.
}

Objects are later loaded into the scene in this manner.

function addObjects(e) {
    // Create the object.
    const entity = document.createElement("a-box")
    entity.setAttribute("scale", {
        x: 20, 
        y: 20,
        z: 20
    })
    entity.setAttribute('material', { color: 'red' } )
    entity.setAttribute('gps-new-entity-place', {
        latitude: e.detail.position.latitude + 0.001,
        longitude: e.detail.position.longitude
    })

    // Set up the click handler.
    entity.addEventListener("click", (evt) => {
        alert("I was clicked!")
    })

    // Add the object to the scene.
    const scene = document.querySelector("a-scene")
    scene.appendChild(entity)
}

When tapping on an object in the scene, the "click" event handler is called successfully on iOS but is NOT called on Android.

What is the current behavior?

From my debugging, I determined that the "click" event is emitted from the "cursor" component's onCursorUp() method. But this method is only called if the "raycaster" component finds intersections in its checkIntersections() method. This method finds those intersections by calling into the three.js Raycaster.intersectObjects() method.

The Raster.intersectObjects() methods returns intersections on iOS, but does not return them on Android.

Note: This solution works on both platforms if the scene is implemented statically using the same markup for the scene. However our application requires the dynamic approach described above.

If the current behavior is a bug, please provide the steps to reproduce. The attached bug.html file provides a simplified implementation of our approach that demonstrates the failure on Android while working successfully on iOS. Tap on the "Get started" button to load the view. The find and tap on the red box in the scene. If successful an alert will show. bug.html.zip

Please mention other relevant information such as the browser version, Operating System and Device Name Testing on iOS 17.3 (iPhone 15 Pro Max) and Android 13 (Pixel 6a)

What is the expected behavior? Click events should work on both iOS and Android.

If this is a feature request, what is motivation or use case for changing the behavior?

im-a-rocketman commented 4 months ago

The feature also seems to be working on Android FireFox. Seems to be an issue with Android Chrome.