Can't get touch events to work properly

Hello, I’m struggling already for sometime with the following. I’m trying to create a click event that allso works on touch devices. I have things working in such a way that the objects are clickable with the mouse but on touch the objects seem to be only clickable when the mouse is hovering over a object and then when the object is being touched it is clickable. Also I noticed that when I click an object with the mouse (for now the function being called is opening up a new window) that when I return to the main window the object is still being selected and dragged/moved by the mouse until I click again. I tried already numerous things and watched many tutorials but I can’t figure things out. Still a newbie here so probably I’m just overlooking something simple (t least that is what i hope). Thanks in advance for looking into this and here is my code:

// Model
let myModel;
let modelPath_MyModel = '/wp-content/uploads/2021/05/new_brain.glb';
let isLoaded = false;

// Material
let texturePath_Enviroment = '/wp-content/uploads/2021/05/Matcap-test34-min.png';
let mat_Enviroment;
let mat_GlassMatCapBack;
let mat_GlassMatCapFront;


let mat_BrainCoreBlue;
let mat_BrainInnerOutterBlue;

let mat_BrainCoreRed;
let mat_BrainInnerOutterRed;
let mat_BrainInnerOutterRed2;
let brainRight;


const statsEnabled = false;

let container, stats;

// three
let scene;
let camera;
let pointer;
let controls;
let renderer;
let delta;
let clock = new THREE.Clock();
let currentIntersect;

let mouseX = 0;
let mouseY = 0;

let targetX = 0;
let targetY = 0;

const windowHalfX = window.innerWidth / 2;
const windowHalfY = window.innerHeight / 2;

function initMainApp () {
	buildScene();
	buildLightEnviroment();
	buildMaterial();
	buildModel();
	watchLoadingManager();
  buildSphereGeometry();
}

function buildScene () {
	const container = document.querySelector('#mainCanvas');

	scene = new THREE.Scene();
	//scene.background = new THREE.Color(0x000000);
  
  camera = new THREE.PerspectiveCamera(30, window.innerWidth / window.innerHeight, 0.1, 100);
	camera.position.z = 14;
	camera.position.y = 1;

	const cameraHolder = new THREE.Group();
	cameraHolder.add(camera);
	scene.add(cameraHolder); 
  
	renderer = new THREE.WebGLRenderer({ container, antialias: true, alpha: true });
	renderer.setSize(window.innerWidth, window.innerHeight);
	
	renderer.shadowMap.enabled = true;
	renderer.shadowMap.type = THREE.PCFSoftShadowMap;
	renderer.shadowMap.needsUpdate = true;
  
					stats = new Stats();
	container.appendChild(renderer.domElement);
  
 // container.onmousemove = function(){
	controls = new THREE.OrbitControls(camera, container );
  //controls.addEventListener('change', render);
	controls.enableDamping = true;
	controls.dampingFactor = 0.08;
	controls.enableZoom = false;
  controls.enablePan = false;
	controls.enabled = true;
	controls.maxAzimuthAngle = Math.PI * 0.2;
	controls.minAzimuthAngle = Math.PI * 1.7;
	controls.maxPolarAngle = 1.7;
	controls.minPolarAngle = 1.2;
	controls.autoRotate = false;
	controls.autoRotateSpeed = 2;
  //controls.addEventListener('mousemove', onDocumentMouseMove, false)
  //controls.update();
}

function buildLightEnviroment () {
	
	const light_Ambient = new THREE.AmbientLight(0xFFFFFF);
	light_Ambient.intensity = 0.75;
	scene.add(light_Ambient);
  
	mat_Enviroment = new THREE.TextureLoader().load(texturePath_Enviroment);
	mat_Enviroment.mapping = THREE.SphericalReflectionMapping;  
}

const fontLoader = new THREE.FontLoader()

fontLoader.load(
'/wp-content/static/Metrophobic_Regular.json',
(font) => 
{

    //Services Text 
 const textGeometry = new THREE.TextBufferGeometry(
 'Services',
   {
     font: font,
     size: 0.17,
     height: 0.03,
     curveSegments: 4,
     bevelEnabled: true,
     bevelThickness: 0.003,
     bevelSize: 0.002,
     bevelOffset: 0,
     bevelSegments: 3,
    }
   )

 const textMaterial = new THREE.MeshMatcapMaterial({
   matcap: mat_Enviroment,
   color: 0x0000ff,
   //shininess: 2500,
   transparent: true,
	 opacity: 1,
    depthWrite: true,
	 //depthTest: true,
	 blending: THREE.AdditiveBlending,
 })
  text = new THREE.Mesh(textGeometry, textMaterial)
  text.position.x = -1.05,
  text.position.y = 0.9,
  text.position.z = 0.35;
 scene.add(text);
  
  //Projects Text
 const textGeometry2 = new THREE.TextBufferGeometry(
 'Projects',
   {
     font: font,
     size: 0.17,
     height: 0.03,
     curveSegments: 4,
     bevelEnabled: true,
     bevelThickness: 0.003,
     bevelSize: 0.002,
     bevelOffset: 0,
     bevelSegments: 3,
    })

 const textMaterial2 = new THREE.MeshMatcapMaterial({
   matcap: mat_Enviroment,
   color: 0xffffff,
   transparent: true,
		opacity: 1,
   depthWrite: true,
	 //depthTest: true,
		blending: THREE.AdditiveBlending,
 })
  text2 = new THREE.Mesh(textGeometry2, textMaterial2)
 
 text2.position.x = -0.42,
 text2.position.y = 2.8;
 text2.position.z = 1.45;
 scene.add(text2);
 
 //Creators Text 
 const textGeometry3 = new THREE.TextBufferGeometry(
 'Creators',
   {
     font: font,
     size: 0.17,
     height: 0.03,
     curveSegments: 4,
     bevelEnabled: true,
     bevelThickness: 0.003,
     bevelSize: 0.002,
     bevelOffset: 0,
     bevelSegments: 3,
    }
   )

  const textMaterial3 = new THREE.MeshMatcapMaterial({
   matcap: mat_Enviroment,
   color: 0xffffff,
   transparent: true, 
   opacity: 0.95,  
   depthWrite: true,
   blending: THREE.AdditiveBlending,
		//side: THREE.FrontSide,
 })
  text3 = new THREE.Mesh(textGeometry3, textMaterial3)
  text3.position.x = 0.15,
  text3.position.y = 1.5,
  text3.position.z = -1.45;
 scene.add(text3);  
  
   gsap.fromTo(text.position, {y: 0.85},{duration: 4, y: 1.05, ease: 'linear.in', yoyo: true, repeat: -1 })
   gsap.fromTo(text2.position, {y: 2.4},{duration: 4, y: 2.75, ease: 'linear.in', yoyo: true, repeat: -1 });
   gsap.fromTo(text3.position, {y: 1.45},{duration: 4, y: 1.5, ease: 'linear.in', yoyo: true, repeat: -1 })
  
  
})

function buildSphereGeometry () {
  
const matcapTexture = new THREE.TextureLoader().load('/wp-content/uploads/2021/05/Matcap-balls36-min.png');

const geometry = new THREE.SphereGeometry( 0.60, 32, 32 );  
const geometryA = new THREE.SphereGeometry( 0.3, 32, 32 );
const geometry1 = new THREE.SphereGeometry( 0.60, 32, 32 );
const geometryB = new THREE.SphereGeometry( 0.3, 32, 32 ); 
const geometry2 = new THREE.SphereGeometry( 0.60, 32, 32 );
const geometryC = new THREE.SphereGeometry( 0.3, 32, 32 ); 
 
  //Blue Ball
const material = new THREE.MeshMatcapMaterial({
  color: 0x03acee, 
  transparent: true, 
  opacity: 0.9,
  depthWrite: true,
  blending: THREE.AdditiveBlending,
})
material.matcap = matcapTexture

 sphere = new THREE.Mesh( geometry, material );
  sphere.position.x = -0.6;
  sphere.position.y = 1;
  sphere.position.z = 0;
  sphere.renderOrder = 2;
  sphere.callback = objectClickHandler;
scene.add( sphere );
  
  //Blue ball inner
  
const materialA = new THREE.MeshPhongMaterial({
  color: 0x03acee,
	  //emissive: 0xFFFF00, 
  transparent: true, 
  opacity: 0.7,
  shininess: 250,
  depthWrite: true,
  blending: THREE.AdditiveBlending,
})
//materialA.matcap = matcapTexture

 sphereA = new THREE.Mesh( geometryA, materialA );
  sphereA.position.y = 1;
  sphereA.position.x = -0.6;
  sphereA.position.z = 0;
  sphereA.renderOrder = 1;
scene.add( sphereA ); 

  //Green Ball
const material2 = new THREE.MeshMatcapMaterial({
  color: 0x00ff00, 
  transparent: true, 
  opacity: 0.9,
  depthWrite: true,
  blending: THREE.AdditiveBlending,
 
})
material2.matcap = matcapTexture
 sphere2 = new THREE.Mesh( geometry1, material2 );
  sphere2.position.y = 2.65;
  sphere2.position.x = 0;
  sphere2.position.z = 1.1;
 sphere2.renderOrder = 2;
  sphere2.callback = objectClickHandler2;
scene.add( sphere2 );
  
  //Green Ball Inner
const materialB = new THREE.MeshPhongMaterial({
  color: 0x00ff00, 
  transparent: true, 
  opacity: 0.7,
  shininess: 250,
  depthWrite: true,
  blending: THREE.AdditiveBlending,
})

 sphereB = new THREE.Mesh( geometryB, materialB );
  sphereB.position.y = 2.65;
  sphereB.position.x = 0;
  sphereB.position.z = 1.1;
  sphereB.renderOrder = 1;
scene.add( sphereB ); 

  //Red Ball
const material3 = new THREE.MeshMatcapMaterial({
  color: 0xfff200, 
  transparent: true, 
  opacity: 0.9,
  depthWrite: true,
  blending: THREE.AdditiveBlending,
})

material3.matcap = matcapTexture
 sphere3 = new THREE.Mesh( geometry2, material3 );
  sphere3.position.x = 0.6;
  sphere3.position.y = 1.525;
  sphere3.position.z = -1.9;
  sphere3.renderOrder = 2;
  sphere3.callback = objectClickHandler3;
scene.add( sphere3 ); 
  
  //Red Ball inner
  
 const materialC = new THREE.MeshPhongMaterial({
  color: 0xfff200,
  transparent: true,
  shininess: 250,
  opacity: 0.9,
  depthWrite: true,
  blending: THREE.AdditiveBlending,
})

 sphereC = new THREE.Mesh( geometryC, materialC );
  sphereC.position.y = 1.525;
  sphereC.position.x = 0.6;
  sphereC.position.z = -1.9;
  sphereC.renderOrder = 1;
scene.add( sphereC ); 
  
   gsap.fromTo(sphere.position, {y: 0.9},{duration: 4, y: 1.1, ease: 'linear.in', yoyo: true, repeat: -1 });
   gsap.fromTo(sphereA.position, {y: 0.9},{duration: 4, y: 1.1, ease: 'linear.in', yoyo: true, repeat: -1 });
   gsap.fromTo(sphere2.position, {y: 2.5},{duration: 4, y: 2.8, ease: 'linear.in', yoyo: true, repeat: -1 });
   gsap.fromTo(sphereB.position, {y: 2.5},{duration: 4, y: 2.8, ease: 'linear.in', yoyo: true, repeat: -1 });
	 gsap.fromTo(sphere3.position, {y: 1.5},{duration: 4, y: 1.55, ease: 'linear.in', yoyo: true, repeat: -1 });
   gsap.fromTo(sphereC.position, {y: 1.5},{duration: 4, y: 1.55, ease: 'linear.in', yoyo: true, repeat: -1 });   
};

  //Raycaster

 raycaster = new THREE.Raycaster();
     
function buildModel () {
	const loader_GLTF = new THREE.GLTFLoader();
	loader_GLTF.load(modelPath_MyModel, function (gltf) {

		myModel = gltf.scene;
		scene.add(myModel);
		myModel.position.y = -2.3;

		myModel.traverse(function (child) {
			if (child.isMesh) {

				child.frustumCulled = false;

				if ( child.name == 'brain_right_core') {          
        child.material = mat_BrainCoreBlue;
        child.renderOrder = 1;
          
        gsap.fromTo(child.scale, {y: 1, x: 1},{duration: 1.5, y: 1.1, x: 1.1, ease: 'none', yoyo: true, repeat: -1 });

        child.castShadow = true;
        child.receiveShadow = true;              

				} else if ( child.name == 'brain_right_inner'  ) {
          child.material = mat_BrainInnerOutterBlue;
					child.renderOrder = 2;
          
          gsap.fromTo(child.scale, {y: 1, x: 1},{duration: 1.5, y: 1.05, x: 1.05, ease: 'none', yoyo: true, repeat: -1 });
          
				} else if ( child.name == 'brain_right_outer' ) {         
					child.material = mat_BrainInnerOutterBlue;
					child.renderOrder = 4;
         
          gsap.fromTo(child.scale, {y: 1, x: 1},{duration: 1.5, y: 1.1, x: 1.1, ease: 'none', yoyo: true, repeat: -1 });

				} else if ( child.name == 'brain_left_core') {
					child.material = mat_BrainCoreRed;
					child.renderOrder = 2;

          gsap.fromTo(child.scale, {y: 1, x: 1},{duration: 1.5, y: 1.1, x: 1.1, ease: 'none', yoyo: true, repeat: -1 });
          
				} else if ( child.name == 'brain_left_inner') {
					child.material = mat_BrainInnerOutterRed;
					child.renderOrder = 3;
					child.castShadow = true;
					child.receiveShadow = true;

          gsap.fromTo(child.scale, {y: 1, x: 1},{duration: 1.5, y: 1.05, x: 1.05, ease: 'none', yoyo: true, repeat: -1 });
          
				} else if ( child.name == 'brain_left_outer') {
					child.material = mat_BrainInnerOutterRed2;
					child.renderOrder = 5;
          
          gsap.fromTo(child.scale, {y: 1, x: 1},{duration: 1.5, y: 1.1, x: 1.1, ease: 'none', yoyo: true, repeat: -1 });

				} else if ( child.name == 'bottle') {
					child.material = mat_GlassMatCapBack;
					child.renderOrder = 6;

					let bottleClone = child.clone();
					bottleClone.material = mat_GlassMatCapFront;

					scene.getObjectByName( "BrainBottle" ).add( bottleClone );
          
        }
			}
		});});
}

function buildMaterial () {

	mat_GlassMatCapBack = new THREE.MeshMatcapMaterial({
		color: 0xFFFFFF,
		matcap: mat_Enviroment,
		side: THREE.BackSide,
		transparent: true,
		opacity: 0.35,
		blending: THREE.AdditiveBlending, // THREE.CustomBlending for normal look
	});

	mat_GlassMatCapFront = new THREE.MeshMatcapMaterial({
		color: 0xFFFFFF,
		matcap: mat_Enviroment,
		side: THREE.FrontSide,
		transparent: true,
		opacity: 0.65,
	  blending: THREE.AdditiveBlending, // THREE.CustomBlending for normal look
	});

	mat_BrainCoreBlue  = new THREE.MeshPhongMaterial({
    color: 0x03acee,
		//emissive: 0x000000,
    shininess: 2500,
  blending: THREE.AdditiveBlending,
		side: THREE.FrontSide,
		depthWrite: false,
		//depthTest: true,
		transparent: true,
		opacity: 0.95,
    
	});
 

	mat_BrainInnerOutterBlue = new THREE.MeshPhongMaterial({
		color: 0x03acee,
		emissive: 0x000000,
    //shininess: 2500,
		blending: THREE.CustomBlending,
		side: THREE.FrontSide,
		depthWrite: false,
		//depthTest: true,
		transparent: true,
		opacity: 0.25,
	});

mat_BrainCoreRed = new THREE.MeshPhongMaterial({
		color: 0xcb5332,
	  emissive: 0x000000,
    shininess: 25,
    blending: THREE.CustomBlending,
		side: THREE.FrontSide,
		depthWrite: false,
		//depthTest: true,
		transparent: true,
		opacity: 0.95,
	});

	mat_BrainInnerOutterRed = new THREE.MeshPhongMaterial({
		color: 0xcb5332,
	  emissive: 0xFFFF00,
    shininess: 25,
		blending: THREE.CustomBlending,
		side: THREE.FrontSide,
		depthWrite: false,
		//depthTest: true,
		transparent: true,
		opacity: 0.25,
	});
  
  mat_BrainInnerOutterRed2 = new THREE.MeshPhongMaterial({
		color: 0x000000,
		emissive: 0xFFFF00,
    shininess: 2500,
		blending: THREE.CustomBlending,
		side: THREE.FrontSide,
		depthWrite: false,
		//depthTest: true,
		transparent: true,
		opacity: 0.15,
	});
}
  
// EVENTS
				
				document.addEventListener( 'mousemove', onDocumentMouseMove );
				window.addEventListener( 'resize', onWindowResize );
 			
function onWindowResize() {
  
  			renderer.setSize( window.innerWidth, window.innerHeight );
        renderer.setPixelRatio(Math.min(window.devicePixelRatio, 2))
				camera.aspect = window.innerWidth / window.innerHeight;
				camera.updateProjectionMatrix();  						
}

function onDocumentMouseMove( event ) {

				mouseX = ( event.clientX - windowHalfX );
				mouseY = ( event.clientY - windowHalfY );
			} 

function objectClickHandler(){
  window.open('/services');
} 
function  objectClickHandler2(){
  window.open('/projects');
}
function  objectClickHandler3(){
  window.open('/creators');
}

	//Cursor
cursor = new THREE.Vector2();


function onDocumentMouseDown(event4) {
  //event4.preventDefault();
  
  {
  pointer.x = event4.pageX / window.width * 2 - 1
  pointer.y = - (event4.pageY / window.height * 2 - 2.95); 
  }
}

window.addEventListener('mousemove', (event3) =>
{
  cursor.x = event3.pageX / window.innerWidth * 2 - 1
  cursor.y = - (event3.pageY / window.innerHeight * 2 - 2.95); 
})




//function onDocumentMouseDown(event4){
 // event4.preventDefault();
  //window.addEventListener( 'mousedown', onDocumentMouseDown );
//window.addEventListener('mousedown', () =>

window.addEventListener('pointerdown',() =>
{
    if(currentIntersect)
    {
      if(currentIntersect.object === sphere)
        {
         sphere.callback();
          
        }
				else if(currentIntersect.object === sphere2)
        { 
          sphere2.callback();
          console.log('click on object 2')
        }
      	else if(currentIntersect.object === sphere3)
        {
          sphere3.callback();
          console.log('click on object 3')
        }
    }
})




function animate () {
	requestAnimationFrame(animate);
  delta = clock.getDelta();
  
  //Cast a Ray
       
raycaster.setFromCamera(cursor, camera)
  
const objectsToTest = [sphere, sphere2, sphere3]
const intersects = raycaster.intersectObjects(objectsToTest)

for(const object of objectsToTest)
  {
    if(object === sphere)
      {
    sphere.material.color.set('#03acee')
  }
    else if(object === sphere2)
      {
     sphere2.material.color.set('#3cb878')
      }
    else if(object === sphere3)
      {
     sphere3.material.color.set('#ec0c57')
      }
for(const intersect of intersects)
  {
    if(object === sphere)
      {
    intersect.object.material.color.set('#6dcff6')
  }
    else if(object === sphere2)
      {
    intersect.object.material.color.set('#a5f3bf')   
      }
    else if(object === sphere3)
      {
    intersect.object.material.color.set('#a5f3bf')   
      }
  }
  }
 if(intersects.length) 
   {
     if(!currentIntersect)
       {
         console.log('mouse enter')
       }
     currentIntersect = intersects[0]
   }
  else
    {
      if(currentIntersect)
        {
          console.log('mouse leave')
        }
      currentIntersect = null
    }

  render();
				if ( statsEnabled ) stats.update();
			}

			function render() {

				targetX = mouseX * .001;
				targetY = mouseY * .001;
        
        	if ( myModel );{
       
					myModel.rotation.y += 0.05 * ( targetX - myModel.rotation.y );
					myModel.rotation.x += 0.05 * ( targetY - myModel.rotation.x );
         }
         
	controls.update()
        
  renderer.render(scene, camera);  
}

function startApplication () {

	animate();
}

function watchLoadingManager () {
	THREE.DefaultLoadingManager.onStart = function ( url, itemsLoaded, itemsTotal ) {
		// console.log('Started loading file: ' + url + '.\nLoaded ' + itemsLoaded + ' of ' + itemsTotal + ' files.');
	};

	THREE.DefaultLoadingManager.onLoad = function () {
		console.log('Loading Complete!');
		isLoaded = true;
		startApplication();

	};

	THREE.DefaultLoadingManager.onProgress = function ( url, itemsLoaded, itemsTotal ) {
		// console.log('Loading file: ' + url + '.\nLoaded ' + itemsLoaded + ' of ' + itemsTotal + ' files.');
	};

	THREE.DefaultLoadingManager.onError = function ( url ) {
		// console.log('There was an error loading ' + url);
	};
  
}

initMainApp();
1 Like

hi @Jeroen
I see you have orbit control to explore your scene and you desire tap/click something, for desktop and mobile… correct?

I suggest you an approach, a different event management between desktop and mobile devices (expecially iOS), I’m not sure that’s the best one solution but in a similar problem I had it worked.
After a device detection, if mobile device, I’ve used pointermove as raycast trigger, using the delta from start touch and event.pageCoords to understand when a user tap to click and when to orbit

  1. Detecting device (probably obsolete! but you can find updated code online)

    let isMobile = false;
    if (
    /(android|bb\d+|meego).+mobile|avantgo|bada/|blackberry|blazer|compal|elaine|fennec|hiptop|iemobile|ip(hone|od)|ipad|iris|kindle|Android|Silk|lge |maemo|midp|mmp|netfront|opera m(ob|in)i|palm( os)?|phone|p(ixi|re)/|plucker|pocket|psp|series(4|6)0|symbian|treo|up.(browser|link)|vodafone|wap|windows (ce|phone)|xda|xiino/i.test(navigator.userAgent, )
    || /1207|6310|6590|3gso|4thp|50[1-6]i|770s|802s|a wa|abac|ac(er|oo|s-)|ai(ko|rn)|al(av|ca|co)|amoi|an(ex|ny|yw)|aptu|ar(ch|go)|as(te|us)|attw|au(di|-m|r |s )|avan|be(ck|ll|nq)|bi(lb|rd)|bl(ac|az)|br(e|v)w|bumb|bw-(n|u)|c55/|capi|ccwa|cdm-|cell|chtm|cldc|cmd-|co(mp|nd)|craw|da(it|ll|ng)|dbte|dc-s|devi|dica|dmob|do(c|p)o|ds(12|-d)|el(49|ai)|em(l2|ul)|er(ic|k0)|esl8|ez([4-7]0|os|wa|ze)|fetc|fly(-|)|g1 u|g560|gene|gf-5|g-mo|go(.w|od)|gr(ad|un)|haie|hcit|hd-(m|p|t)|hei-|hi(pt|ta)|hp( i|ip)|hs-c|ht(c(-| ||a|g|p|s|t)|tp)|hu(aw|tc)|i-(20|go|ma)|i230|iac( |-|/)|ibro|idea|ig01|ikom|im1k|inno|ipaq|iris|ja(t|v)a|jbro|jemu|jigs|kddi|keji|kgt( |/)|klon|kpt |kwc-|kyo(c|k)|le(no|xi)|lg( g|/(k|l|u)|50|54|-[a-w])|libw|lynx|m1-w|m3ga|m50/|ma(te|ui|xo)|mc(01|21|ca)|m-cr|me(rc|ri)|mi(o8|oa|ts)|mmef|mo(01|02|bi|de|do|t(-| |o|v)|zz)|mt(50|p1|v )|mwbp|mywa|n10[0-2]|n20[2-3]|n30(0|2)|n50(0|2|5)|n7(0(0|1)|10)|ne((c|m)-|on|tf|wf|wg|wt)|nok(6|i)|nzph|o2im|op(ti|wv)|oran|owg1|p800|pan(a|d|t)|pdxg|pg(13|-([1-8]|c))|phil|pire|pl(ay|uc)|pn-2|po(ck|rt|se)|prox|psio|pt-g|qa-a|qc(07|12|21|32|60|-[2-7]|i-)|qtek|r380|r600|raks|rim9|ro(ve|zo)|s55/|sa(ge|ma|mm|ms|ny|va)|sc(01|h-|oo|p-)|sdk/|se(c(-|0|1)|47|mc|nd|ri)|sgh-|shar|sie(-|m)|sk-0|sl(45|id)|sm(al|ar|b3|it|t5)|so(ft|ny)|sp(01|h-|v-|v )|sy(01|mb)|t2(18|50)|t6(00|10|18)|ta(gt|lk)|tcl-|tdg-|tel(i|m)|tim-|t-mo|to(pl|sh)|ts(70|m-|m3|m5)|tx-9|up(.b|g1|si)|utst|v400|v750|veri|vi(rg|te)|vk(40|5[0-3]|-v)|vm40|voda|vulc|vx(52|53|60|61|70|80|81|83|85|98)|w3c(-| )|webc|whit|wi(g |nc|nw)|wmlb|wonu|x700|yas-|your|zeto|zte-/i.test(navigator.userAgent.substr(0, 4),) ) {
    isMobile = true;
    }

2)Separating behaviour
The code it’s not complete, it’s another project, but i hope that thanks to the variable names you can understand the concept

    container.style.touchAction = 'none';// in my project works better
      if (isMobile) {
        container.addEventListener('pointerdown', (event) => {
          firstTouch = true;
          startX = event.pageX;
          startY = event.pageY;
          isSwiping = false;
        });
        container.addEventListener('pointermove', (event) => {
          if (firstTouch) {
            startX = event.pageX;
            startY = event.pageY;
            firstTouch = false;
          } else {
            const diffX = Math.abs(event.pageX - startX);
            const diffY = Math.abs(event.pageY - startY);
            if (diffX < delta && diffY < delta ) {
              onDocumentTouchClick(event); //your callback
            }
          }
          isSwiping = true; 
        });
        container.addEventListener('pointerup', (event) => {//try anyway for pointerup, it's not a problem and for some Android it works
          const diffX = Math.abs(event.pageX - startX);
          const diffY = Math.abs(event.pageY - startY);
          if (diffX < delta && diffY < delta) {
            onDocumentMouseClick(event); //you can youse the same
          }
          firstTouch = true;
        });
      } else {
        container.addEventListener('pointerdown', (event) => {
          isSwiping = false;
          startX = event.pageX;
          startY = event.pageY;
        });
        container.addEventListener('pointermove', () => {
          isSwiping = true;
        });
        container.addEventListener('pointerup', (event) => {
          const diffX = Math.abs(event.pageX - startX);
          const diffY = Math.abs(event.pageY - startY);
          if (diffX < delta && diffY < delta) {
            onDocumentMouseClick(event);
          }
        });
      }

I hope it helps

Hello @alessandro_guarino thanks for your reply! I will try to to get your option working. Much appreciated!