Пользовательский переключатель Angular не работает на мобильных устройствах

#javascript #angular #typescript #angular2-template

#javascript #angular #typescript #angular2-шаблон

Вопрос:

Я пытаюсь создать пользовательский переключатель в Angular. Все работает, как ожидалось, на рабочем столе, но не на мобильном устройстве. Итак, я нажимаю и перетаскиваю вправо. Вот как это должно работать на рабочем столе, на мобильном устройстве мне нужно нажать и сдвинуть вправо. Это не работает.

Здесь у меня есть живой пример codesandbox.

Что я делаю не так?

 import { Component, ViewChild, ElementRef, Renderer2 } from "@angular/core";

@Component({
  selector: "app-root",
  templateUrl: "./app.component.html",
  styleUrls: ["./app.component.css"]
})
export class AppComponent {
  @ViewChild("theSlider") theSlider: ElementRef;
  @ViewChild("lock") theLock: ElementRef;
  @ViewChild("banText") banText: ElementRef;
  @ViewChild("timerText") timerText: ElementRef;

  myPos = 0;
  posX = 0;
  borderLeft = 2;
  borderRight = 62;
  wasSlide = 0;
  easing = 0;
  step = 0;
  duration = 30;
  repeater;

  mousemoveUnlistener;
  mouseupUnlistener;
  touchstartUnlistener;
  touchendUnlistener;

  constructor(private renderer: Renderer2) {}

  sliderDown(e) {
    if (e.cancelable) {
      e.preventDefault();
      e.stopPropagation();

      e = e || window.event;

      this.posX = e.clientX;
      if (this.wasSlide !== 2) {
        this.wasSlide = 1;
      }

      this.mousemoveUnlistener = this.renderer.listen(
        "document",
        "mousemove",
        (evt) => {
          this.dragSlider(evt);
        }
      );

      this.mouseupUnlistener = this.renderer.listen(
        "document",
        "mouseup",
        (evt) => {
          this.closeDrag();
        }
      );

      this.touchstartUnlistener = this.renderer.listen(
        "document",
        "touchstart",
        (evt) => {
          this.dragSlider(evt);
        }
      );

      this.touchendUnlistener = this.renderer.listen(
        "document",
        "touchend",
        (evt) => {
          this.closeDrag();
        }
      );
    }
  }

  // SLIDER MOUSE DRAG
  dragSlider(e) {
    e = e || window.event;
    e.preventDefault();
    if (this.wasSlide !== 2) {
      this.wasSlide = 0;
    }
    this.myPos = this.posX - e.clientX;
    this.posX = e.clientX;
    if (this.theSlider.nativeElement.offsetLeft < this.borderLeft - 1) {
      this.closeDrag();
    } else if (this.theSlider.nativeElement.offsetLeft > this.borderRight) {
      this.theSlider.nativeElement.style.left = this.borderRight   "px";
    } else {
      this.theSlider.nativeElement.style.left =
        this.theSlider.nativeElement.offsetLeft - this.myPos   "px";
    }
  }

  // SLIDER MOUSE UP
  closeDrag() {
    if (this.theSlider.nativeElement.offsetLeft < this.borderLeft) {
      this.theSlider.nativeElement.style.left = this.borderLeft   "px";
    } else if (this.theSlider.nativeElement.offsetLeft > this.borderRight - 1) {
      this.theSlider.nativeElement.style.left = this.borderRight   "px";
      this.expandSliderAnim();
    } else if (
      this.theSlider.nativeElement.offsetLeft < this.borderRight amp;amp;
      this.theSlider.nativeElement.offsetLeft > this.borderLeft   3
    ) {
      // JUMPBACK
      // this.theStartValue = this.theSlider.offsetLeft;
      this.moveMe();
    }

    if (this.mousemoveUnlistener) {
      this.mousemoveUnlistener();
    }

    if (this.mouseupUnlistener) {
      this.mouseupUnlistener();
    }

    if (this.touchstartUnlistener) {
      this.touchstartUnlistener();
    }

    if (this.touchendUnlistener) {
      this.touchendUnlistener();
    }
  }

  // SLIDER EXPAND ANIMATION
  expandSliderAnim() {
    // add animation
    this.theSlider.nativeElement.style.animationName = "sliderExpands";
    this.theSlider.nativeElement.style.animationDuration = "300ms";
    this.theSlider.nativeElement.style.animationFillMode = "forwards";
    // add count down timer

    this.timerText.nativeElement.style.display = "block";
    // this.theSlider.nativeElement.innerHTML =
    // "<span id='timer'>"   /*timer here:*/ '23:59:59' /*///*/   "</span><div id='lock' #lock></div>";
    this.banText.nativeElement.style.display = "none";
    this.theSlider.nativeElement.style.background =
      "radial-gradient(50% 50% at 50% 50%, #338EFC 0%, #0450AD 100%)";
    // lock icon animation
    // let theLock = document.getElementById('lock');
    this.theLock.nativeElement.style.animationName = "lockFadeIn";
    this.theLock.nativeElement.style.animationDuration = "2s";
    // theLock.style.animationFillMode = "forwards";
    this.theLock.nativeElement.style.animationDirection = "alternate";
    this.theLock.nativeElement.style.animationIterationCount = "infinite";

    // document.getElementById('gameName').style.opacity = String(0.3);
    // document.getElementById('depositButton').style.opacity = String(0.3);
    // document.getElementById('sessionTimer').style.opacity = String(0.3);
    setTimeout(function () {
      this.wasSlide = 2;
    }, 1000);
  }

  explainBanButton() {
    if (this.wasSlide === 2) {
      alert("You are blocked from playing for 23:59:59 hours");
      this.wasSlide = 2;
    } else if (this.wasSlide === 1) {
      this.wasSlide = 0;
    }
  }

  // OPEN MODAL WINDOW (TODO) TO EXPLAIN SESSION TIMER FUNCTIONALITY TO THE USER
  explainSessionTimer() {
    alert(
      "this indicates how much time has past since you start you seesion today"
    );
  }

  moveMe() {
    // using fix values here, because the sliders
    // moves between fix constrains
    this.wasSlide = 0;
    this.easing = this.easeInCubic(this.step, 0, 12, this.duration);
    this.theSlider.nativeElement.style.left = this.easing   "px";
    this.step  ;
    if (this.step > this.duration) {
      cancelAnimationFrame(this.repeater);
      this.step = 0;
    } else {
      // bind the context to the func.
      this.repeater = requestAnimationFrame(this.moveMe.bind(this));
    }
  }

  easeInCubic(currentIteration, startValue, changeInValue, totalIterations) {
    return changeInValue / Math.pow(currentIteration, 0.5)   startValue;
  }
}
  

Шаблон:

 <div id="ban_button" (touchstart)="explainBanButton($event)" (mouseup)="explainBanButton($event)">
  <div id="slider" #theSlider (touchend)="sliderDown($event)" (touchstart)="closeDrag($event)" (mousedown)="sliderDown($event)" (mouseup)="closeDrag($event)">
    <span id="ban_text" #banText>Ban</span>
    <div #timerText style="display: none;">
      <span id='timer'>23:59:59</span><div id='lock' #lock></div>
    </div>
  </div>
  <span class="ban_button--time__text">24h</span>
  <div id="h24"></div>
</div>
  

Комментарии:

1. Пример в ссылке не работает

2. Это работает, вы можете попробовать еще раз?

3. Да, проверьте ответ

Ответ №1:

Несколько вещей:

1-й

touchstart и touchend должны быть переключены, не так ли?

введите описание изображения здесь

2-й

Вы регистрируетесь dragSlider touchstart . Я считаю, что так и должно быть touchmove .

введите описание изображения здесь

3-й

По крайней мере, при мобильной эмуляции настольных браузеров я сталкиваюсь с несуществующим случаем else, когда я меняю 1-й и 2-й.

введите описание изображения здесь

Комментарии:

1. Я внес изменения 1 и 2, и я получаю эту ошибку несколько раз. [Intervention] Unable to preventDefault inside passive event listener due to target being treated as passive. See <URL> других ошибок нет