在RXJS中重新创建ContextMenu事件

发布于 2025-01-30 16:54:46 字数 835 浏览 1 评论 0原文

我想重新创建

用普通语言,该观察值应发出:

  • 触摸start事件发生
  • 在2000毫秒(基本上是长压)
  • ,然后触摸端,

当时不应发出:触摸端在:

  • 触摸端在不到2000毫秒中发生在2000毫秒中
  • ,触摸start事件之后是touch move事件,

我无法弄清楚如何跳过触摸端,如果触摸端发生较早或接触触点后面是触摸机。这就是我到目前为止的:

const touchStart$ = fromEvent<TouchEvent>(this.el.nativeElement, "touchstart");
const touchEnd$ = fromEvent<TouchEvent>(this.el.nativeElement, "touchend");
const touchMove$ = fromEvent<TouchEvent>(this.el.nativeElement, "touchmove");
const contextmenu$ = touchStart$.pipe(
      switchMap(event => touchEnd$.pipe(mapTo(event))),
      switchMap(event => timer(2000).pipe(mapTo(event), takeUntil(merge(touchEnd$, touchMove$))))
);

contextmenu$.subscribe($event => {
      console.log("CONTEXTMENU EVENT HAPPENED");
});

I want to recreate the contextmenu event from touch events in RxJS because iOS does not support the contextmenu event on touch.

In plain language, this observable should emit when:

  • the touchstart event occurred
  • for 2000ms (basically long-press)
  • followed by touchend

It should not emit when:

  • the touchend occurs in less than 2000ms
  • the touchstart event is followed by touchmove event

I can't figure out how to skip if the touchend occurs sooner or if the touchstart is followed by touchmove. This is what I've so far:

const touchStart$ = fromEvent<TouchEvent>(this.el.nativeElement, "touchstart");
const touchEnd$ = fromEvent<TouchEvent>(this.el.nativeElement, "touchend");
const touchMove$ = fromEvent<TouchEvent>(this.el.nativeElement, "touchmove");
const contextmenu$ = touchStart$.pipe(
      switchMap(event => touchEnd$.pipe(mapTo(event))),
      switchMap(event => timer(2000).pipe(mapTo(event), takeUntil(merge(touchEnd$, touchMove$))))
);

contextmenu$.subscribe($event => {
      console.log("CONTEXTMENU EVENT HAPPENED");
});

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

泪之魂 2025-02-06 16:54:46

您的解决方案可以简化一点。内部mapto不需要,如果您不重复使用name event,则可以在结尾处使用单个mapto你的管道。另外,您可能需要使用take(1)而不是takeuntil(touchMove $) 在Inner switchmap上第一次排放之后:

  const longPress$ = this.touchStart$.pipe(
    switchMap(event => timer(2000).pipe(
      takeUntil(merge(touchMove$, touchEnd$)),
      switchMap(() => touchEnd$.pipe(take(1))),
      mapTo(event)
    ))
  );

我假设您得到了想要的行为,但是我认为通常会在持续时间通过时会发射。即,我们不需要等待touchend事件。如果是这种情况,它会变得更加简单:

  const longPress$ = this.touchStart$.pipe(
    switchMap(event => timer(2000).pipe(
      takeUntil(merge(touchMove$, touchEnd$)),
      mapTo(event)
    ))
  );

这里有几个带有彩色伐木的堆叠式:原始 | 简化

Your solution can be simplified a little bit. The inner mapTo isn't necessary, if you don't reuse the name event, you can just use a single mapTo at the end of your pipe. Also, you may want to use take(1) instead of takeUntil(touchMove$) on the inner switchMap since you want to end the stream after the first emission:

  const longPress$ = this.touchStart$.pipe(
    switchMap(event => timer(2000).pipe(
      takeUntil(merge(touchMove$, touchEnd$)),
      switchMap(() => touchEnd$.pipe(take(1))),
      mapTo(event)
    ))
  );

I'm assuming you got the behavior you wanted, but I think normally a longpress will fire when duration passes; i.e. we needn't wait for the touchend event. If that were the case, it gets even simpler:

  const longPress$ = this.touchStart$.pipe(
    switchMap(event => timer(2000).pipe(
      takeUntil(merge(touchMove$, touchEnd$)),
      mapTo(event)
    ))
  );

Here are a couple StackBlitzes with colorful logging: Original | Simplified

π浅易 2025-02-06 16:54:46

我提出了一个可能的解决方案:

const touchStart$ = fromEvent<TouchEvent>(this.el.nativeElement, "touchstart");
const touchEnd$ = fromEvent<TouchEvent>(this.el.nativeElement, "touchend");
const touchMove$ = fromEvent<TouchEvent>(this.el.nativeElement, "touchmove");
const contextmenu$ = touchStart$.pipe(
    switchMap(event =>
        timer(2000).pipe(
           mapTo(event),
           takeUntil(merge(touchMove$, touchEnd$)),
           switchMap(event => touchEnd$.pipe(mapTo(event), takeUntil(touchMove$)))
        )
    )
);

contextmenu$.subscribe($event => {
    console.log("CONTEXT MENU EVENT HAPPENED");
});

I came up with a possible solution:

const touchStart$ = fromEvent<TouchEvent>(this.el.nativeElement, "touchstart");
const touchEnd$ = fromEvent<TouchEvent>(this.el.nativeElement, "touchend");
const touchMove$ = fromEvent<TouchEvent>(this.el.nativeElement, "touchmove");
const contextmenu$ = touchStart$.pipe(
    switchMap(event =>
        timer(2000).pipe(
           mapTo(event),
           takeUntil(merge(touchMove$, touchEnd$)),
           switchMap(event => touchEnd$.pipe(mapTo(event), takeUntil(touchMove$)))
        )
    )
);

contextmenu$.subscribe($event => {
    console.log("CONTEXT MENU EVENT HAPPENED");
});
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文