# 移动端滑动方向判断

# 1. 介绍

移动端,滑动方向判断。

相关事件:

移动端事件 说明 类比 PC 端的事件
touchstart 按下 mousedown
touchmove 按住滑动 mousemove
touchend 抬起 mouseup

# 2. 示例

interface IOptions {
  minDeltaDistance: number
}

function getDefaults(): IOptions {
  return {
    minDeltaDistance: 60,
  };
}

interface IPoint {
  x: number,
  y: number,
}
export enum Direction {
  Up = 'up',
  Down = 'down',
  Right = 'right',
  Left = 'left',
}

export class SwipeDetect {
  private el: HTMLElement;

  private options: IOptions;

  private listener: (d: Direction) => void;

  private startPoint: IPoint = { x: 0, y: 0 };

  private endPoint: IPoint = { x: 0, y: 0 };

  private isMoved = false;

  constructor(el: HTMLElement, listener: (d: Direction) => void, options = getDefaults()) {
    this.el = el;
    this.listener = listener;
    this.options = options;

    this.bindEvents();
  }

  private bindEvents() {
    this.el.addEventListener('touchstart', this.onTouchStart, false);
    this.el.addEventListener('touchmove', this.onTouchMove, false);
    this.el.addEventListener('touchend', this.onTouchEnd, false);
  }

  public destroy() {
    this.el.removeEventListener('touchstart', this.onTouchStart, false);
    this.el.removeEventListener('touchmove', this.onTouchMove, false);
    this.el.removeEventListener('touchend', this.onTouchEnd, false);

    this.el = null as any;
    this.options = null as any;
    this.listener = null as any;
  }

  private onTouchStart = (e: TouchEvent) => {
    const { screenX, screenY } = e.touches[0];
    this.startPoint.x = screenX;
    this.startPoint.y = screenY;
  };

  private onTouchMove = (e: TouchEvent) => {
    // Prevent default will stop user from scrolling, use with care
    e.preventDefault();

    this.isMoved = true;
  };

  private onTouchEnd = (e: TouchEvent) => {
    if (!this.isMoved) {
      return;
    }

    const { screenX, screenY } = e.changedTouches[0];
    this.endPoint.x = screenX;
    this.endPoint.y = screenY;

    const deltaX = this.endPoint.x - this.startPoint.x;
    const deltaY = this.endPoint.y - this.startPoint.y;
    const { minDeltaDistance } = this.options;

    this.reset();

    if (deltaX ** 2 + deltaY ** 2 < minDeltaDistance ** 2) {
      return;
    }

    let direction: Direction;

    if (deltaY === 0 || Math.abs(deltaX / deltaY) > 1) {
      direction = deltaX > 0 ? Direction.Right : Direction.Left;
    } else {
      direction = deltaY > 0 ? Direction.Down : Direction.Up;
    }

    this.listener(direction);
  };

  private reset() {
    this.isMoved = false;
    this.startPoint = { x: 0, y: 0 };
    this.endPoint = { x: 0, y: 0 };
  }
}

# 3. 参考

本章目录