javascript - How to differentiate between pinch or zoom inout using touch pad and mouse wheel event - Stack Overflow

I had implemented zoom inout an image using mousewheel event which is successfully working. But the be

I had implemented zoom in/out an image using mousewheel event which is successfully working. But the behavior is different when I do that with touchpad(using two fingers to zoom in/out). How to differentiate beetween mousewheel event and touchpad events.

I had implemented zoom in/out an image using mousewheel event which is successfully working. But the behavior is different when I do that with touchpad(using two fingers to zoom in/out). How to differentiate beetween mousewheel event and touchpad events.

Share Improve this question edited Jan 31, 2020 at 11:27 user2083041 asked May 7, 2018 at 6:39 user2083041user2083041 5231 gold badge10 silver badges32 bronze badges
Add a ment  | 

3 Answers 3

Reset to default 3

The same wheel event unfortunately fires for both pinch and mouse wheel, so it doesn't seem possible at this time to use a different event.

However, I found that the mouse wheel tends to trigger the e.deltaY number in a larger way than pinching.

Thus, I have a listener like so:

const handleZoom = (e) => {
  e.preventDefault();

  // ignore mouse wheel events that have bigger steps
  if (Math.abs(e.deltaY) > 25) {
    return;
  }

  // do what you want to do with pinching here
}
document.addEventListener("wheel", handleZoom);

You can play with the 25 variable to suit your own needs. But for the most part, I noticed that pinch movements are usually much more subtle and have a delta closer to 0, whereas mouse wheel events usually trigger a larger scroll.

Touchpad two-finger gestures always emit wheel event. However you can distinguish touchpad from mouse event by looking at the deltas and making some reasonable assumptions, and you can distinguish zoom from scroll by checking the ctrlKey value of the event. You can also determine scroll direction by looking at the deltas and the shiftKey of the event.

The only caveat is holding Ctrl key while swiping on the trackpad results in an actual scroll, but the ctrlKey value of the event is true in the same way as when the trackpad is pinched. So we can additionally listen for keydown/keyup on Ctrl to determine if Ctrl was really pressed while pinching or whether ctrlKey was set to true automatically due to pinching the trackpad.

Here's a working example:

// TRY IT
// document.addEventListener("wheel", (e) =>
//   console.log(getWheelType(e), getWheelDirection(e)),
// );

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

const WHEEL_TYPES = {
  TRACK_ZOOM: "TRACK_ZOOM",
  TRACK_SCROLL: "TRACK_SCROLL",
  MOUSE_ZOOM: "MOUSE_ZOOM",
  MOUSE_SCROLL: "MOUSE_SCROLL",
};

const DIRECTIONS = {
  UP: "UP",
  DOWN: "DOWN",
  LEFT: "LEFT",
  RIGHT: "RIGHT",
  IN: "IN",
  OUT: "OUT",
};

const getWheelType = (event) => {
  if (!(event instanceof WheelEvent)) {
    throw "Event must be a WheelEvent";
  }

  if (isWheelZoom(event)) {
    if (isWheelMouse(event)) {
      return WHEEL_TYPES.MOUSE_ZOOM;
    }
    return WHEEL_TYPES.TRACK_ZOOM;
  }

  // Not a zoom, so must be a scroll
  if (isWheelMouse(event)) {
    return WHEEL_TYPES.MOUSE_SCROLL;
  }
  return WHEEL_TYPES.TRACK_SCROLL;
};

const getWheelDirection = (event) => {
  if (!(event instanceof WheelEvent)) {
    throw "Event must be a WheelEvent";
  }

  const maxDelta =
    Math.abs(event.deltaX) > Math.abs(event.deltaY)
      ? event.deltaX
      : event.deltaY;

  if (event.ctrlKey && (isWheelMouse(event) || !isCtrlKeyPressed)) {
    // it's a zoom
    return getDeltaZoomDirection(maxDelta);
  }

  if (event.shiftKey) {
    // Holding Shift while turning wheel or swiping trackpad in any direction
    // results sideways scrolls (OS dependent of course, but seems to be the
    // case on most).
    //
    // So we assume that if Shift was held, that it's a horizontal scroll.
    return getMaxDeltaScrollDirection(maxDelta, 0);
  } else {
    // Otherwise, take the larger of the two deltas as indicating direction
    return getMaxDeltaScrollDirection(event.deltaX, event.deltaY);
  }
};

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

let isCtrlKeyPressed = false;

const onPress = (e) => {
  if (e.key === "Control") {
    isCtrlKeyPressed = true;
    document.removeEventListener("keydown", onPress);
    document.addEventListener("keyup", onDepress);
  }
};

const onDepress = (e) => {
  if (e.key === "Control") {
    isCtrlKeyPressed = false;
    document.addEventListener("keydown", onPress);
    document.removeEventListener("keyup", onDepress);
  }
};

// NOTE this only works if the page is focused
document.addEventListener("keydown", onPress);

const isWheelMouse = (event) => {
  if (!(event instanceof WheelEvent)) {
    throw "Event must be a WheelEvent";
  }

  // If exactly one of deltaX or deltaY is non-0,
  // and is greater than 50, it's very likely a mouse wheel.
  // Otherwise assume a trackpad.
  if (
    (event.deltaX === 0) !== (event.deltaY === 0) &&
    Math.abs(event.deltaX + event.deltaY) > 50
  ) {
    return true;
  }
  return false;
};

const isWheelZoom = (event) => {
  if (!(event instanceof WheelEvent)) {
    throw "Event must be a WheelEvent";
  }

  // If ctrlKey is set, then it's a zoom: either pinching trackpad or holding
  // Ctrl while turning mouse wheel.
  return event.ctrlKey === true;
};

const getMaxDeltaScrollDirection = (deltaX, deltaY) => {
  if (deltaX === deltaY) {
    return null;
  }

  if (Math.abs(deltaX) > Math.abs(deltaY)) {
    return deltaX < 0 ? DIRECTIONS.LEFT : DIRECTIONS.RIGHT;
  }

  return deltaY < 0 ? DIRECTIONS.UP : DIRECTIONS.DOWN;
};

const getDeltaZoomDirection = (delta) => {
  if (delta === 0) {
    return null;
  }

  return delta < 0 ? DIRECTIONS.IN : DIRECTIONS.OUT;
};

Edit: this code was further refined and became part of a library I released, which among other things can handle gestures (scroll, zoom, drag) by one or more devices (key, wheel, touch, pointer).

First, you have to be careful when designing more advanced touch interactions: when the user uses a mouse it will respond via a click event, but when the user touches the screen both touch and click events will occur. For a single click the order of events is:

1) touchstart 2) touchmove 3) touchend 4) mouseover 5) mousemove 6) mousedown 7) mouseup 8) click

This, of course, means that if you are processing touch events like touchstart, you need to make sure that you don’t process the corresponding mousedown and/or click event as well. If you can cancel the touch events (call preventDefault() inside the event handler), then no mouse events will get generated for touch.

Update: You can identify touch or click like this: `

$('#element-id').on('click touchend',function(e){
  if(e.type=='click')
      console.log('Mouse Click');
  else
      console.log('Touch');
});

`

发布者:admin,转转请注明出处:http://www.yc00.com/questions/1745358956a4624272.html

相关推荐

发表回复

评论列表(0条)

  • 暂无评论

联系我们

400-800-8888

在线咨询: QQ交谈

邮件:admin@example.com

工作时间:周一至周五,9:30-18:30,节假日休息

关注微信