Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Three.js Mobile iOS v8.4 how to treat touchEvents as mouseEvents?

According to caniuse.com webgl is supported by Safari and Chrome browsers for iOS versions 8.1 thru 8.4.

From an iPad (which runs the mobile version of iOS 8.4) it seems that many of the official Three.js webgl demos run alright. For example on this draggable cubes demo the trackball works by (finger) touch & drag. However I cannot get it to react to a finger tap, or finger touch/hold/release as a mouseclick (to be fair nor does that work on my Android 4.1 device). This interactive voxel painter doesn't run at all on the iPad (but works fine on my Android 4.1 device).

Surprisingly this three.js mouseclick demo by Lee Stemkoski does work as desired in terms of finger tap --> (interpreted as) --> mouseclick, but unfortunately it uses an old (unsupported) version of Three.js (r60 from year 2013).

So my question: "Is there a way to code an app using latest version of Three.js so that a finger tap on a mobile iOS (8.4) device is treated as a mouse-click?

EDIT

After hunting around a bit I found a useful source of information on processing touch events.

like image 850
steveOw Avatar asked Nov 22 '25 02:11

steveOw


1 Answers

This solution is just a workaround but it does the job for me. It intercepts and handles touchstart events in Android 4.1 and iPad/iOS 8.

The "official" way seems to be to catch the touch event and then create a mouse click event and dispatch it. The synthetic click event should then be picked up by our Click event listener and passed to the chosen click handler function. But I cannot get it to work so that the click handler receives the client x,y coordinates of the touch.

So I simply handled the touch event in the touch catcher function (in my case 'touchstart' is all I am interested in), and extracted the touch client x,y coordinates, and processed them, and passed the results to a touch position handler (which is where the mouse click handler would have passed on to).

  //... You need to put this line, or similar, in F_Init:-

 document.addEventListener( 'touchstart', F_event_Touch_onDocument_handle, false ); 

//===========================================================================================

function  F_event_Touch_onDocument_handle( evt ) 
{

  evt.preventDefault();  //... this prevents window from sliding about.

  //------------------------------------------------------------------------------------

  if (evt.touches.length > 1 || (evt.type == "touchend" && evt.touches.length > 0))
    //... if more than 1 touch detected then ignore.
    return;

    //------------------------------------------------------------------------------------

  var reaction_type = null;
  var touch = null;

  //... see here for event types  http://www.w3schools.com/jsref/dom_obj_event.asp  

  switch (evt.type) 
  {
    case "touchstart": 
      touch = evt.changedTouches[0]; //... specify which touch for later extraction of XY position values.
      reaction_type = "onclick"; 
      break;
    case "touchmove": // I don't use this
      reaction_type = "mousemove";
      touch = evt.changedTouches[0];
      break;
    case "touchend":  // I don't use this     
      reaction_type = "mouseup";
      touch = evt.changedTouches[0];
      break;
  }

  if (reaction_type == "onclick")
  {
        //----------------------------------------------------------------

        // METHOD A (WORKAROUND)  //
        // Works OK
        // instead of dispatching a click event and letting our mouseClick event handler catch it
        //  we determine the touch x and y coordinates
        //  then pass them to the next function in the chain after the mouseClick event handler.

        thisTouch.x =   ( touch.clientX / window.innerWidth ) * 2 - 1;
        thisTouch.y = - ( touch.clientY / window.innerHeight ) * 2 + 1;

        xxx = F_see_if_Click_was_on_a_ThreeJS_Object( thisTouch.x, thisTouch.y );

        //----------------------------------------------------------------

        // METHOD B (OLD MOZILLA) //
        //  copied from "Handling Clicks" tutorial: https://developer.mozilla.org/en-US/docs/Web/API/Touch_events#Example
        // * does not work, our Click event handler does not pickup touch.clientX and touch.clientY as numbers.
        // * initMouseEvent is deprecated... see https://developer.mozilla.org/en-US/docs/Web/API/MouseEvent/initMouseEvent 
        if {1 == 2)
        {
            var newEvt = document.createEvent("MouseEvents");

            newEvt.initMouseEvent( reaction_type, true, true, evt.originalTarget.ownerDocument.defaultView, 0, touch.screenX, touch.screenY, touch.clientX, touch.clientY, evt.ctrlKey, evt.altKey, evt.shiftKey, evt.metaKey, 0, null);

            evt.originalTarget.dispatchEvent(newEvt);
        }

      //----------------------------------------------------------------

    } // if (reaction_type == "onclick").
}
//... EOF F_event_Touch_onDocument_handle().

//=================================================================
like image 91
steveOw Avatar answered Nov 24 '25 10:11

steveOw



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!