Angular 自定义切换在移动设备上不起作用
Angular custom toggle not working on mobile
我正在尝试在 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 &&
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>
几件事:
第一
touchstart 和 touchend 应该互换,不是吗?
第二
您用 touchstart
注册了 dragSlider
。我认为应该是 touchmove
.
第三
至少在桌面浏览器移动仿真中,当我更改第一个和第二个时,我 运行 进入不存在的其他情况。
我正在尝试在 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 &&
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>
几件事:
第一
touchstart 和 touchend 应该互换,不是吗?
第二
您用 touchstart
注册了 dragSlider
。我认为应该是 touchmove
.
第三
至少在桌面浏览器移动仿真中,当我更改第一个和第二个时,我 运行 进入不存在的其他情况。