iPhone Safari touch events issue

Hi everyone,

I’m having a problem with the Safari browser on my iPhone. The problem is that the objects are not clickable, but the click event works perfectly in desktop browsers and Chrome on iPhone.
for more information: Panning with orbitcontrols on the iPhone works. Only when I want to click on an object on the scene, the click event doesn’t work.

Here are some of my codes:
Has anyone else been in this situation?

var mouse = new THREE.Vector2(),
 INTERSECTED;
var intersected;

function onDocumentTouchStart(event) {
 if (event.touches.length == 1) {
   mouse.x = (event.touches[0].pageX / window.innerWidth) * 2 - 1;
   mouse.y = -(event.touches[0].pageY / window.innerHeight) * 2 + 1;
 }
}
function onDocumentTouchMove(event) {
 if (event.touches.length == 1) {
   event.preventDefault();
   mouse.x = (event.touches[0].pageX / window.innerWidth) * 2 - 1;
   mouse.y = -(event.touches[0].pageY / window.innerHeight) * 2 + 1;
 }
}
function onDocumentTouchEnd(event) {
 if (event.touches.length == 1) {
   mouse.x = (event.touches[0].pageX / window.innerWidth) * 2 - 1;
   mouse.y = -(event.touches[0].pageY / window.innerHeight) * 2 + 1;
 }
}

window.addEventListener("touchstart", onDocumentTouchStart, false);
window.addEventListener("touchmove", onDocumentTouchMove, false);
window.addEventListener("touchend", onDocumentTouchEnd, false);

let isMobile = false;
if (
 navigator.userAgent.match(/Android/i) ||
 navigator.userAgent.match(/webOS/i) ||
 navigator.userAgent.match(/iPhone/i) ||
 navigator.userAgent.match(/iPad/i) ||
 navigator.userAgent.match(/iPod/i) ||
 navigator.userAgent.match(/BlackBerry/i) ||
 navigator.userAgent.match(/Windows Phone/i)
) {
 isMobile = true;
}
window.addEventListener("click", (event) => {
 event.preventDefault();
 mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
 mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;

 raycaster.setFromCamera(mouse, camera);

 const intersects = raycaster.intersectObjects([...sceneMeshes, ...cubes]);

 if (intersects.length > 0 && currentIntersect) {
   for (let i = 0; i < intersects.length; i++) {
     cameraTurnAndLook(currentIntersect);
     currentIntersect = intersects[0];
   }
 }
});

function onMouseMove(event) {
 event.preventDefault();
 mouse.x = (event.clientX / window.innerWidth) * 2 - 1;
 mouse.y = -(event.clientY / window.innerHeight) * 2 + 1;
 raycaster.setFromCamera(mouse, camera);
 const intersects = raycaster.intersectObjects([...sceneMeshes, ...cubes]);
 if (intersects.length) {
   if (!currentIntersect) {
     $("html,body").css("cursor", "crosshair");
   }
   currentIntersect = intersects[0].object;
 } else {
   if (currentIntersect) {
     $("html,body").css("cursor", "context-menu");
   }
   currentIntersect = null;
 }
}
window.addEventListener("mousemove", onMouseMove, false);

if (!isMobile) {
 window.addEventListener("touchstart", (event) => {
   if (event.touches.length == 1) {
     mouse.x = (event.touches[0].pageX / window.innerWidth) * 2 - 1;
     mouse.y = -(event.touches[0].pageY / window.innerHeight) * 2 + 1;
   }
   raycaster.setFromCamera(mouse, camera);
   const intersects = raycaster.intersectObjects([...sceneMeshes, ...cubes]);
   if (intersects.length > 0 && currentIntersect) {
     for (let i = 0; i < intersects.length; i++) {
       camera.getWorldPosition(camerapos);
       cameraTurnAndLook(currentIntersect);
       currentIntersect = intersects[0];
     }
   }
 });
}

maybe i’ve overlooked something but in your touchstart event you’re using a value that’s never defined…

  if (intersects.length > 0 && currentIntersect) {

currentIntersect looks like it’s only ever defined in the mousemove event which doesn’t exist for mobile devices as well as the click event which does exist for mobile devices although it effectively fires on mouseup || touchend which of course is fired later than touchstart… does it work if you remove currentIntersect from the touchstart event eg.

  if (intersects.length > 0) {

if so you’ll just need to sort some logic to define currentIntersect in another place for mobile interactions…

Yes, it works fine, but it still lacks Safari touch event functionality. Touchmove to pan with orbitcontrols works, but touch event that triggers object click does not.

:thinking: if you enable the web inspector in safari ios do you get any evident console warnings or errors?


if not it may be worth adding some console logs of your own to different parts of your click event to determine which point in the code is preventing this from working

No, I have not any error on console. I added a console.log to alarm when trigger a click but nothing appears

do you get the alert if you remove this line?

No. I didn’t get any error

:thinking: I’m just trying to boot up an old iphone to test this as it sounds off, can you try running the following pen, clicking anywhere in the preview and seeing if the alert pops up in safari?

1 Like

No alert pops up doesn’t show on safari

It Works my friend. what’s the difference?

reload and try the pen again…

apparently it’s a known bug on safari ios

looks like the style of the event container, in this case body needs the css style cursor : pointer; added… to be honest i’d sack off click events and use pointer events instead as they are more reliable and also accessible from both desktop and mobile devices.

Thank you.