What's the best way to detect a 'touch screen' device using JavaScript?

后端 未结 30 3050
花落未央
花落未央 2020-11-21 23:50

I\'ve written a jQuery plug-in that\'s for use on both desktop and mobile devices. I wondered if there is a way with JavaScript to detect if the device has touch screen capa

30条回答
  •  我在风中等你
    2020-11-22 00:22

    The problem

    Due to hybrid devices which use a combination of touch and mouse input, you need to be able dynamically change the state / variable which controls whether a piece of code should run if the user is a touch user or not.

    Touch devices also fire mousemove on tap.

    Solution

    1. Assume touch is false on load.
    2. Wait until a touchstart event is fired, then set it to true.
    3. If touchstart was fired, add a mousemove handler.
    4. If the time between two mousemove events firing was less than 20ms, assume they are using a mouse as input. Remove the event as it's no longer needed and mousemove is an expensive event for mouse devices.
    5. As soon as touchstart is fired again (user went back to using touch), the variable is set back to true. And repeat the process so it's determined in a dynamic fashion. If by some miracle mousemove gets fired twice on touch absurdly quickly (in my testing it's virtually impossible to do it within 20ms), the next touchstart will set it back to true.

    Tested on Safari iOS and Chrome for Android.

    Note: not 100% sure on the pointer-events for MS Surface, etc.

    Codepen demo


    const supportsTouch = 'ontouchstart' in window;
    let isUsingTouch = false;
    
    // `touchstart`, `pointerdown`
    const touchHandler = () => {
      isUsingTouch = true;
      document.addEventListener('mousemove', mousemoveHandler);
    };
    
    // use a simple closure to store previous time as internal state
    const mousemoveHandler = (() => {
      let time;
      
      return () => {
        const now = performance.now();
    
        if (now - time < 20) {
          isUsingTouch = false;
          document.removeEventListener('mousemove', mousemoveHandler);
        }
    
        time = now;
      }
    })();
    
    // add listeners
    if (supportsTouch) {
      document.addEventListener('touchstart', touchHandler);
    } else if (navigator.maxTouchPoints || navigator.msMaxTouchPoints) {
      document.addEventListener('pointerdown', touchHandler);
    }
    

提交回复
热议问题