События Swipe работают на Chrome для iphone, но не для инструментов разработчика Android / Chrome - PullRequest
0 голосов
/ 08 июля 2019

Я написал пользовательские события смахивания на основе учебника Google для этого: https://developers.google.com/web/fundamentals/design-and-ux/input/touch/

Конструкция включает два выдвижных ящика, один спускается сверху, другой - снизу. Поведение смахивания прекрасно работает в Firefox, Chrome (когда не в режиме адаптивного дизайна) и Safari. Это также работает на iPhone.

Однако не работает , когда я переключаюсь в режим адаптивного дизайна в Chrome, и, похоже, не работает в Chrome на Android. События touchstart, touchmove и touchend запускаются правильно, но что-то в Android и Chrome (в режиме RD), кажется, упреждающе останавливает или отменяет жесты. Я попытался отладить, но ничего не работает, и Google не показывает ничего.

Свойство position указывает на то, доступен ли этот верхний ящик или нет.

Вот код:

window.requestAnimFrame = (function(){
    return  window.requestAnimationFrame       ||
            window.webkitRequestAnimationFrame ||
            window.mozRequestAnimationFrame    ||
            function( callback ){
              window.setTimeout(callback, 1000 / 60);
            };
  })();


// ^ Check for pointer events support...

var pointerDownName = "pointerdown";
var pointerUpName = "pointerup";
var pointerMoveName = "pointermove";

if (window.navigator.msPointerEnabled) {
  pointerDownName = "MSPointerDown";
  pointerUpName = "MSPointerUp";
  pointerMoveName = "MSPointerMove";
}

// Simple way to check if some form of pointerevents is enabled or not
window.PointerEventsSupport = false;
if (window.PointerEvent || window.navigator.msPointerEnabled) {
  window.PointerEventsSupport = true;
}

class Swiper {
  constructor(element, position, otherSwiper, search) {
    this.search = search;
    this.element = element;
    this.position = position;
    this.otherSwiper = otherSwiper;

    this.IN_STATE = 1;
    this.OUT_STATE = 2;
    this.differenceInY = 0;
    this.rafPending = false;
    //   * where the touch happens
    this.initialTouchPos = null;
    // * where the last touch happened
    this.lastTouchPos = null;
    this.open = true;
    this.scrollThreshold;
    this.itemHeight = element.offsetHeight;

    if (this.position === "top") {
      this.inTransformVal = -(element.offsetHeight * 0.85);
      this.outTransformVal = -(element.offsetHeight * 0.08);
      this.OTHER_ONE_inTransformVal = element.offsetHeight * 0.85;
      this.OTHER_ONE_outTransformVal = element.offsetHeight * 0.08;
    } else {
      this.inTransformVal = element.offsetHeight * 0.85;
      this.outTransformVal = element.offsetHeight * 0.08;
      this.OTHER_ONE_inTransformVal = -(element.offsetHeight * 0.85);
      this.OTHER_ONE_outTransformVal = -(element.offsetHeight * 0.08);
    }

    if (this.position == "top"){
        this.inputs = document.querySelectorAll(".drawer__jp__input");
    }

    this.startTransform = this.inTransformVal;

    //   * where the bottom of the div is currently located
    // * the transform value is -(500 - currentYPosition)

    this.currentState = this.IN_STATE;

    // Perform client width here as this can be expensive and doens't
    // change until window.onresize

    // *   the height of the div
    this.slopValue = this.itemHeight * (1 / 4);

    this.handleGestureStart = this.handleGestureStart.bind(this);
    this.handleGestureMove = this.handleGestureMove.bind(this);
    this.handleGestureEnd = this.handleGestureEnd.bind(this);
    this.updateSwipeRestPosition = this.updateSwipeRestPosition.bind(this);
    this.changeState = this.changeState.bind(this);
    this.getGesturePointFromEvent = this.getGesturePointFromEvent.bind(this);
    this.addListeners = this.addListeners.bind(this);
    this.onAnimFrame = this.onAnimFrame.bind(this);
    this.addListeners();
  }

  handleGestureStart(evt) {



    if (this.otherSwiper.currentState !== this.otherSwiper.IN_STATE) {
      this.otherSwiper.changeState(this.otherSwiper.IN_STATE);
    }

    if (evt.touches && evt.touches.length > 1) {
      return;
    }

    // Add the move and end listeners
    if (window.PointerEvent) {
      evt.target.setPointerCapture(evt.pointerId);

    } else {
      // Add Mouse Listeners
      document.addEventListener("mousemove", this.handleGestureMove, true);
      document.addEventListener("mouseup", this.handleGestureEnd, true);
    }

    this.initialTouchPos = this.getGesturePointFromEvent(evt);
    this.element.style.transition = "initial";
  }

  handleGestureMove(evt) {

    evt.preventDefault();

    if (!this.initialTouchPos) {
      return;
    }

    this.lastTouchPos = this.getGesturePointFromEvent(evt);

    if (this.rafPending) {
      return;
    }

    this.rafPending = true;

    window.requestAnimFrame(this.onAnimFrame);
  }

  handleGestureEnd(evt) {

    evt.preventDefault();


    if (evt.touches && evt.touches.length > 0) {
      return;
    }

    this.rafPending = false;

    // Remove Event Listeners
    if (window.PointerEvent) {
      evt.target.releasePointerCapture(evt.pointerId);
    } else {
      // Remove Mouse Listeners
      document.removeEventListener("mousemove", this.handleGestureMove, true);
      document.removeEventListener("mouseup", this.handleGestureEnd, true);
    }

    this.updateSwipeRestPosition();

    this.initialTouchPos = null;
  }

  updateSwipeRestPosition() {

    let differenceInY = this.initialTouchPos.y - this.lastTouchPos.y;
    let currentTransform = this.startTransform - differenceInY;
    let newState = this.currentState;

    if (Math.abs(differenceInY) > this.slopValue) {
      if (this.currentState === this.IN_STATE) {
        if (this.position === "top") {
          if (differenceInY > 0) {
            newState = this.IN_STATE;
          } else {
            newState = this.OUT_STATE;
          }
        } else {
          if (differenceInY < 0) {
            newState = this.IN_STATE;
          } else {
            newState = this.OUT_STATE;
          }
        }
      } else {
        if (this.position === "top") {
          if (this.currentState === this.OUT_STATE && differenceInY > 0) {
            newState = this.IN_STATE;
          } else if (
            this.currentState === this.OUT_STATE &&
            differenceInY < 0
          ) {
            newState = this.OUT_STATE;
          }
        } else {
          if (this.currentState === this.OUT_STATE && differenceInY < 0) {
            newState = this.IN_STATE;
          } else if (
            this.currentState === this.OUT_STATE &&
            differenceInY > 0
          ) {
            newState = this.OUT_STATE;
          }
        }
      }
    } else {
      newState = this.currentState;
    }

    this.element.style.transition = "all 150ms ease-out";
    this.changeState(newState);
  }

  changeState(newState) {


    let transformStyle;
    switch (newState) {
      case this.IN_STATE:
        this.startTransform = this.inTransformVal;
        if (this.position === "top"){
            this.inputs.forEach(input => {
                input.style.opacity = 0;
            })
        }
        break;
      case this.OUT_STATE:
        this.startTransform = this.outTransformVal;
        if (this.position === "top"){
            this.inputs.forEach(input => {
                input.style.opacity = 1;
            })
        }
        break;
    }

    this.transformStyle =
      "translateY(" + this.startTransform + "px) translateX(-50%)";

    this.element.style.msTransform = this.transformStyle;
    this.element.style.MozTransform = this.transformStyle;
    this.element.style.webkitTransform = this.transformStyle;
    this.element.style.transform = this.transformStyle;

    this.currentState = newState;

    if (this.position === "top" && this.currentState === this.OUT_STATE){
        Swiper.underline.classList.add("open")
      } else {
          Swiper.underline.classList.remove("open")
      }
  }

  getGesturePointFromEvent(evt) {

    var point = {};

    if (evt.targetTouches) {
      point.x = evt.targetTouches[0].clientX;
      point.y = evt.targetTouches[0].clientY;
    } else {
      // Either Mouse event or Pointer Event
      point.x = evt.clientX;
      point.y = evt.clientY;
    }


    return point;
  }

  onAnimFrame() {

    if (!this.rafPending) {
      return;
    }

    let differenceInY = this.initialTouchPos.y - this.lastTouchPos.y;

    let newYTransform = this.startTransform - differenceInY;
    let transformStyle;


    if (this.position === "top") {
      if (newYTransform < -5) {
        transformStyle = `translateY(${newYTransform}px) translateX(-50%)`;
        if (this.currentState === this.OUT_STATE) {
            this.inputs.forEach(input => {
                input.style.opacity = 1 - (differenceInY / 100);
            })
        } 
      }
    } 
    else {
      if (newYTransform > 5) {
        transformStyle = `translateY(${newYTransform}px) translateX(-50%)`;
      }
    }

    this.element.style.webkitTransform = transformStyle;
    this.element.style.MozTransform = transformStyle;
    this.element.style.msTransform = transformStyle;
    this.element.style.webkitTransform = transformStyle;
    this.element.style.transform = transformStyle;

    this.rafPending = false;
  }

  addListeners() {

    if (window.PointerEvent) {

      // Add Pointer Event Listener
      this.element.addEventListener(
        "pointerdown",
        this.handleGestureStart,
        true
      );
      this.element.addEventListener(
        "pointermove",
        this.handleGestureMove,
        true
      );
      this.element.addEventListener("pointerup", this.handleGestureEnd, true);
      this.element.addEventListener(
        "pointercancel",
        this.handleGestureEnd,
        true
      );
    } 
    else {
      // Add Touch Listener
      this.element.addEventListener(
        "touchstart",
        this.handleGestureStart,
        true
      );
      this.element.addEventListener("touchmove", this.handleGestureMove, true);
      this.element.addEventListener("touchend", this.handleGestureEnd, true);
      this.element.addEventListener("touchcancel", this.handleGestureEnd, true);

      // Add Mouse Listener
      this.element.addEventListener("mousedown", this.handleGestureStart, true);

    }

    // if (this.search) {
    //     this.search.addEventListener("click", (e) => {
    //         if (this.currentState === this.IN_STATE){
    //             this.changeState(this.OUT_STATE)
    //         }
    //     }, true)
    // }

  }
}

window.addEventListener("load", function() {


  setTimeout(() => {
    var h = Math.max(
      document.documentElement.clientHeight,
      window.innerHeight || 0
    );

    const main = document.querySelector(".main");





    window.onresize = function() {
        main.setAttribute("style",`height:${h}px`);
    };

    Swiper.underline = document.querySelector('.jp__header__underline');

    window.onresize();

    const topDrawer = document.querySelector(".drawer__container--top");
    const bottomDrawer = document.querySelector(".drawer__container--bottom");


    const search = document.querySelector(".drawer__search__form");
    const bottomSwiper = new Swiper(bottomDrawer, "bottom", null, search);
    const topSwiper = new Swiper(topDrawer, "top", bottomSwiper, null);
    bottomSwiper.otherSwiper = topSwiper;


    const wrapper = document.querySelector(".searchbar-input")

    const map = document.querySelector(".map__container")
    const searchInput = document.querySelector(".drawer__search__input");

    map.addEventListener("click", () => {
        bottomSwiper.changeState(bottomSwiper.IN_STATE)
        topSwiper.changeState(topSwiper.IN_STATE)
        searchInput.value = "";

    })

  }, 500);
});

Было бы здорово узнать, если у кого-то еще была подобная проблема ...

...