export default function blockTouch()

in packages/bui-utils/src/touchBlocker.ts [11:116]


export default function blockTouch(root) {
  let lastTouch;
  let moveDirection;
  let moveAxis;

  const onTouchStart = (e) => {
    [lastTouch] = e.touches;
  };
  const shouldPrevent = (targetElement, axis, delta) => {
    let el = targetElement;
    let needPrevent = true;
    while (el) {
      const { overflowY, overflowX } = window.getComputedStyle(el);
      if (axis === 'y' && (overflowY === 'scroll' || overflowY === 'auto')) {
        const dir = moveDirection || delta;
        if (moveDirection === undefined) moveDirection = dir;

        if (el.scrollTop !== 0 && dir < 0) {
          needPrevent = false;
          break;
        }
        // 当内部滚动元素高度有小数时,可能会出现小于号左右差1的情况导致算法失效
        if (el.scrollTop + el.offsetHeight + 1 < el.scrollHeight && dir > 0) {
          needPrevent = false;
          break;
        }
      }
      if (axis === 'x' && (overflowX === 'scroll' || overflowX === 'auto')) {
        const dir = moveDirection || delta;
        if (moveDirection === undefined) moveDirection = dir;
        if (el.scrollLeft !== 0 && dir < 0) {
          needPrevent = false;
          break;
        }
        if (el.scrollLeft + el.offsetWidth < el.scrollWidth && dir > 0) {
          needPrevent = false;
          break;
        }
      }

      if (el === root) break;
      el = el.parentNode;
    }
    return needPrevent;
  };
  const onTouchMove = (e) => {
    const currentTouch = e.touches[0];
    // 如果单指在滑动的时候另一只手指碰到屏幕一次而滑动手指不放开,就会触发touchend清空lastTouch引发这个问题
    if (!lastTouch || !currentTouch) return;
    if (!moveAxis) {
      if (
        Math.abs(lastTouch.screenY - currentTouch.screenY) >
        Math.abs(lastTouch.screenX - currentTouch.screenX)
      )
        moveAxis = 'y';
      if (
        Math.abs(lastTouch.screenY - currentTouch.screenY) <
        Math.abs(lastTouch.screenX - currentTouch.screenX)
      )
        moveAxis = 'x';
    }

    if (
      shouldPrevent(
        e.target,
        moveAxis,
        moveAxis === 'x'
          ? lastTouch.screenX - currentTouch.screenX
          : lastTouch.screenY - currentTouch.screenY,
      ) &&
      !e.cancelable === false
    )
      e.preventDefault();
    // setLastTouch(e.touches[0]);
  };
  const onTouchEnd = (e) => {
    if (e.touches.length !== 0) return;
    lastTouch = undefined;
    moveDirection = undefined;
    moveAxis = undefined;
  };
  const onScroll = (e) => {
    if (
      shouldPrevent(
        e.target,
        Math.abs(e.deltaX) > Math.abs(e.deltaY) ? 'x' : 'y',
        Math.abs(e.deltaX) > Math.abs(e.deltaY) ? e.deltaX : e.deltaY,
      ) &&
      !e.cancelable === false
    )
      e.preventDefault();

    moveDirection = undefined;
  };

  root.addEventListener('touchstart', onTouchStart);
  root.addEventListener('touchmove', onTouchMove);
  root.addEventListener('touchend', onTouchEnd);
  root.addEventListener('wheel', onScroll);
  return () => {
    root.removeEventListener('touchstart', onTouchStart);
    root.removeEventListener('touchmove', onTouchMove);
    root.removeEventListener('touchend', onTouchEnd);
    root.removeEventListener('wheel', onScroll);
  };
}