rxjs - 鼠标悬停时暂停通知流,鼠标悬停时恢复
问题描述
我有这个显示/隐藏通知的流:
this.subscription = this.notificationsApi.notifications$.pipe(
concatMap((event) => {
return of(event).pipe(
delay(450),
tap(() => {
this.notification = event;
this.isActive = true;
this.cd.markForCheck();
}),
delay(isDefined(event.showFor) ? event.showFor : this.hideAfter),
/// Pause here if you hover over the notification ///
tap(() => {
this.isActive = false;
this.cd.markForCheck();
}),
delay(450)
);
})
).subscribe(() => {});
我想做的是在您将鼠标悬停在通知上时暂停流,并在您不再将鼠标悬停在通知上时继续:
<div (mouseover)="pause()" (mouseout)="continue()"></div>
这是我似乎无法找到适用于这种情况的解决方案的地方。我假设我必须再使用 1-2Subject
秒,然后switchMap
根据您是暂停还是继续使用,但就像我说的那样,我无法弄清楚到底如何。
我尝试查看此 StackBlitz 以获得 switchMap 暂停/恢复功能,但是当我尝试这种方法时,它根本没有显示任何通知。
任何指针?
解决方案
主要技巧是至少等待
- 通知显示延迟
- 以及流中的下一条消息
并让鼠标进出来增加延迟。
里面的魔力concatMap
做到了(至少,我认为它确实......)
首先,我们notifications$
对它进行延迟和 concatMap。因此,每个味精都会至少显示DELAY
一次
注意:伪代码
notifications$.concatMap(msg =>
timer(DELAY)
.ignoreElements()
.startWith(msg)
)
然后我们想让鼠标延迟延迟
notifications$
.concatMap(msg =>
mouse$
.switchMap(isOver => { // < We re-delay on mouse state change
if (isOver) {
return empty() // < Do nothing when user hovers
}
return timer(DELAY); // < after DELAY -- take in next msgs
})
// we need only one completion event from this mouse$+ stream
.take(1)
// existing logic to turn delay stream into msg stream with delay
.ignoreElements()
.startWith(msg)
)
最后,如果下一条消息出现在 DELAY 之后——我们仍然需要监听鼠标悬停和延迟。
// store current msg index
let currentMsgIndex = -1;
notifications$
// store current msg index
.map((msg,i) => {
currentMsgIndex = i;
return msg;
})
.concatMap((msg, i) => {
// we listen to events from the mouse
return memMouse$
// if mouse pos changed -- reeval timeout
.switchMap(value => {
// do nothing on mouse in
if (value) {
return empty();
}
// until next msg comes in -- we're tracking mouse in/out
let nextMsgAwait$;
if (i == currentMsgIndex) {
// current msg is latest
nextMsgAwait$ = notifications$.pipe(take(1));
} else {
// we already have next msgs to show
nextMsgAwait$ = of(void 0);
}
// if mouse is away -- wait for
// - timer for TIMEOUT
// - and till new msg arrives
// until then -- user can mouse in/out
// to delay the next msg display
return forkJoin(
timer(TIMEOUT)
, nextMsgAwait$
);
}),
// we need only one completion event from this mouse$+ stream
.take(1)
// existing logic to turn delay stream into msg stream with delay
.ignoreElements()
.startWith(msg)
})
为了更好地理解,请参见上面提到的例子——我在那里添加了一些评论。
推荐阅读
- python - 将多个 ImageDataGenerator 的输出合并到一个张量
- arduino - Arduino LED Matrix 从串口接收数据非常慢
- python - 在循环中多次更改变量的值
- node.js - 发出 post 请求后,如何使用 Vue.js 向用户显示从 express 到用户的一系列错误
- google-chrome-devtools - 在谷歌浏览器中未捕获(承诺)未定义
- javascript - 在 Javascript 中读取会话值
- python - flask_sqlalchemy 从不同的文件创建模型
- ios - iOS(今日)小部件 - 通过点击应用程序图标启动应用程序
- eclipse - BIRT 报表设计器:带有页码和超链接的目录 (TOC)
- java - 在同等优先级的情况下保持 PriorityQueue 插入顺序