Raycaster on MOBILE?

Works perfectly on PC, but on Mobile, the following barely works. Sometimes I can get a click to register, but rarely. Clicking in random spots doesn’t seem to register other objects, so I’ve assumed that maybe it isn’t an X/Y issue. Any examples on this? (Note the touchend event at the end)

I’m probably doing something silly, and just need to test more to realize what it is. Hoping someone might just point out my stupid though :smiley:

let ilist = []
const raycaster = new THREE.Raycaster()
const pointer = new THREE.Vector2(),
domClick = ((e)=>{
  pointer.x = ( e.clientX / window.innerWidth ) * 2 - 1
    pointer.y = - ( e.clientY / window.innerHeight ) * 2 + 1
  raycaster.setFromCamera( pointer, camera )
  const intersects = raycaster.intersectObjects( scene.children )
  toploop: for ( let i = 0; i < intersects.length; i ++ ) {
    let obj = intersects[ i ].object
    for ( let key in pobjs ) {
      if ( pobjs[key].id == obj.id ) {
        if ( key == 'MC' ) {
          console.log( "'" + ilist.join("', '") + "'" )
          ilist = []
        } else {
          ilist.push( key )
        }
        console.log( "CLICKED: '" + key + "'" )
        //alert('Clicked ' + key)
        break toploop
      }
    }
  }      
})

renderer.domElement.addEventListener("click", domClick)
renderer.domElement.addEventListener("touchend", domClick)

Is your canvas element always properly resized to fit the entire window inner width / inner height?

1 Like

Yes,

Although its the child of a DIV, the width is set to 100% and height is set to 100vh. It perfectly sizes. Turning phone vertical or horizontal flips proportionately, no scroll bar and it fills completely. (In the future it won’t be filling the entire screen, but since it currently is I figured this should scale correctly and the same compared to desktop)

Listen for pointersown pointermove and pointerup

Click doesn’t fire until the touch is released and touchend also fires when touch is released… so they are redundant.

1 Like

Thanks I’ll do some research and play with it! Haven’t really done much mobile stuff at all, and although it’s not a priority atm, I want to make sure I can interact with objects on the canvas for this project on mobile in the future.

If touchEvent used, you need to get a specific touch from TouchEvent.changedTouches, i.e. on beginning of domClick you have to add something like

e = e.changedTouches?.[0] || e; 
2 Likes

Ahhhh duh, this was it. Thanks! I completely forgot about e.touches, was just playing with them in February, and on the project this is being implemented into lol.

Final solution, as this won’t use 100% width / height, and can move.

  if ( e.touches ) {
    if ( e.touches.length > 1 ) { return }
    e = e.touches[0]
  }
  const rect = renderer.domElement.getBoundingClientRect()
  pointer.x = ((e.clientX - rect.x) / width) * 2 - 1
  pointer.y = -((e.clientY - rect.y) / height) * 2 + 1

Actually it’s better to use changedTouches, because it contains only the touches triggered the event.

1 Like

Thanks! added a comment / reminder to research, for when I’m working on the new UI.

1 Like