我想用rxjs为我的网站实现一个滚动监听器。监听器当前发出每个滚动号码。如果数字高于之前没有存储STATEFULL属性,是否可以实现仅发出滚动位置的滚动侦听器。我想只与运营商解决这个问题。目前的实现如下:
public lastScrolledHeight: number = 0;
...
public ngOnInit() {
this.listenForScroll()
.subscribe(scrollHeight => {
this.showAddButton = this.lastScrolledHeight >= scrollHeight; // true or false
this.lastScrolledHeight = scrollHeight;
});
}
private listenForScroll(): Observable<number> {
return fromEvent(window, 'scroll').pipe(
debounceTime(25),
map((e: any) => e.path[1].scrollY)
);
}
一种方法可能是添加startsWith(0)
运算符。这将初始位置排到0.但如果scan()
,filter()
或reduce()
会有所帮助,我不能说。
我向下滚动到Y = 300。应该发出300。我向上滚动到Y = 50.什么都不应该发出。我再次向下滚动到150,应该发出150。
由于对我以前的方法不满意,我决定创建一个包含rxjs.filter
的自定义运算符,并使用谓词将当前值与前一个值进行比较:
// it will take a predicate to compare values
// by default it will behave as distinctUntilChanged()
const filterChanges = (predicate = ((a,b) => a!==b)) => {
// store previous value
let prevValue = void 0;
return pipe(
filter((value, index)=>{
// pass through the first value on stream
if (index === 0) {
prevValue = value;
return value;
}
// compare current with prev
const result = predicate(value, prevValue);
prevValue = value;
return result;
})
);
};
然后就像传递比较器一样简单:
source$.pipe(
filterChanges((a, b) => a > b)
)
输出:
希望这可以帮助
我想,你可以使用pairwise:
source$.pipe(
startWith(-1),
pairwise(),
switchMap(([a,b])=>
b > a
? of(b)
: EMPTY
)
)
检查此代码in a playground
希望这可以帮助
你可以使用scan
运算符和distinctUntilChanged
:
return fromEvent(window, 'scroll').pipe(
debounceTime(25),
map((e: any) => e.path[1].scrollY),
scan((prev, curr) => Math.max(prev, curr), 0),
distinctUntilChanged()
)
会发生什么是修改observable以包含当前和上一次迭代的最大值(并且值为0作为其初始值)。
之后,distinctUntilChanged()
确保观察者不会发出重复事件。
这可确保您只接收大于前一个值的值。
虽然我非常感谢@Kos和@Daniel的帮助,因为我花时间帮助我找到一个干净的解决方案,但我发现了一种干净简单的方法。
fromEvent(document, 'scroll').pipe(
debounceTime(50),
// get scrollY
map((e: any) => e.path[1].scrollY),
startWith(0),
distinctUntilChanged(),
// map the last scroll values into an array
pairwise(),
// returns true if delta of prev & curr is greaterOrEqual 0 => scroll up
map(([prev, curr]: Array<number>) => prev - curr >= 0)
);