我想使用rxjs为我的网站实现滚动侦听器。侦听器当前发出每个scrollY号。如果数字大于之前的不存储状态全属性,是否可以实现只显示滚动位置的滚动侦听器。我只想和运营商解决这个问题。当前的实现如下所示:
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。
答案 0 :(得分:2)
我想,您可以为此成对使用
source$.pipe(
startWith(-1),
pairwise(),
switchMap(([a,b])=>
b > a
? of(b)
: EMPTY
)
)
检查此代码in a playground
希望这会有所帮助
答案 1 :(得分:1)
您可以将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()
)
发生的事情是将可观察对象修改为包含当前迭代和上一个迭代的最大值(并且其初始值为0)。
此后,distinctUntilChanged()
确保可观察对象不会发出重复事件。
这可以确保您只会收到比上一个更大的值。
答案 2 :(得分:1)
对我以前的方法不满意,我决定创建一个包含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)
)
输出:
这里有一个playground example。
希望这会有所帮助
答案 3 :(得分:1)
尽管我非常感谢@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)
);