我想检测mousedown
何时被发射超过500毫秒,如果是的话-做点什么。我的尝试:
const button = document.querySelector('button')
const stream = Rx.Observable.fromEvent(button, 'mousedown')
const mouseUp$ = Rx.Observable.fromEvent(button, 'mouseup')
stream.delay(500).takeUntil(mouseUp$).subscribe(() => console.log(1))
它有效,但仅在第一次运行时可用。然后,由于takeUntil
运算符而取消了该流。如何使其每次都能工作?
答案 0 :(得分:3)
在每个express.static()
事件中启动TimerObservable
持续500毫秒。如果mouseDown$
在mouseUp$
起的500毫秒内unsubscribe
被发射。
TimerObservable
RxJS> = 6.0.0
const button = document.querySelector('button')
const mouseDown$ = Rx.Observable.fromEvent(button, 'mousedown')
const mouseUp$ = Rx.Observable.fromEvent(button, 'mouseup')
const stream$ = mouseDown$.switchMap(() => Rx.Observable.TimerObservable(500).takeUntil(mouseUp$));
stream$.subscribe(() => console.log('Only Fired after 500ms'))
答案 1 :(得分:1)
鼠标保持指令的示例:
@Directive({ selector: "[appMouseHold]" })
export class MouseHoldDirective implements OnInit, OnDestroy {
@Input() set appMouseHold(tick: string | number) {
if (typeof tick === 'string') {
tick = parseInt(tick, 10);
}
this.tick = tick || 500;
}
private tick: number;
private readonly _stop = new Subject<void>();
private readonly _start = new Subject<void>();
private subscription: Subscription;
@Output() mousehold = new EventEmitter<number>();
@Output() mouseholdstart = new EventEmitter<void>();
@Output() mouseholdend = new EventEmitter<void>();
ngOnInit() {
this.subscription = this._start
.pipe(
tap(() => this.mouseholdstart.emit()),
switchMap(() =>
timer(500, this.tick).pipe(
takeUntil(this._stop.pipe(tap(() => this.mouseholdend.emit())))
)
)
)
.subscribe((tick) => {
this.mousehold.emit(tick);
});
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
@HostListener("mousedown", ["$event"])
onMouseDown($event) {
if ($event.button === 0) {
this._start.next();
}
}
@HostListener("mouseup")
onMouseUp() {
this._stop.next();
}
}
请参见Stackblitz
对于非角度使用,您可以简单地将@HostListener
处理程序替换为fromEvent()
可观察对象
答案 2 :(得分:0)
SplitterAlex's answer很好,但是takeUntil()
完成了可观察的操作,您无法再处理事件,因此我的解决方法是(无法完成可观察的操作)
public touchStartSubject: Subject<any> = new Subject<any>();
public touchStartObservable: Observable<any> = this.touchStartSubject.asObservable();
public touchEndSubject: Subject<any> = new Subject<any>();
public touchEndObservable: Observable<any> = this.touchEndSubject.asObservable();
@HostListener('touchstart', ['$event'])
public touchStart($event: TouchEvent): void {
this.touchStartSubject.next($event);
}
@HostListener('touchend', ['$event'])
public touchEnd(): void {
this.touchEndSubject.next(null);
}
this.touchStartObservable
.pipe(
mergeMap((res) => race(
timer(1500).pipe(map(() => res)),
this.touchEndObservable,
)),
)
.subscribe((res: TouchEvent) => {
if (!res) return;
// do stuff
})
如果有人可以在没有if (!res) return;
条件的情况下(例如,使用.error
代替.next
的{{1}}