我正在尝试基于另外两个创建新的observable。我有:
var mouseClickObservable = Rx.Observable.fromEvent(this.canvas, "click");
var mouseMoveObservable = Rx.Observable.fromEvent(this.canvas, "mousemove");
function findObject(x, y) {/* logic for finding object under cursor here. */}
var objectUnderCursor = this.mouseMoveObservable.select(function (ev) {
return findObject(ev.clientX, clientY);
});
我想创建objectClicked observable,它应该在用户点击对象时产生值。我可以再次调用findObject,如下所示:
var objectClicked = this.mouseClickObservable.select(function (ev) {
return findObject(ev.clientX, clientY);
});
但这是非常耗时的功能。
我目前使用的另一种方法是将最后一个悬停的对象存储在变量中,但我认为,应该有纯粹的功能方式来做到这一点。我试着像这样使用Observable.join:
var objectClicked = this.objectUnderCursor.join(
mouseClickObservable,
function (obj) { return this.objectUnderCursor },
function (ev) { return Rx.Observable.empty() },
function (obj, ev) { return obj })
但它只需点击一次即可生成多个值
答案 0 :(得分:0)
我没有看到您实际订阅的任何代码到您定义的任何这些可观察对象,因此很难提供一个好的答案。你真的需要在每次移动鼠标时调用findObject
吗?当鼠标移动时,您是否需要提供某种悬停效果?或者您只需要知道被点击的对象,在这种情况下,您只需要在点击时调用findObject
一次?
假设您只需要知道点击了什么对象,您甚至不用担心鼠标移动,只需执行以下操作:
var objectClicked = mouseClickObservable
.select(function (ev) { return findObject(ev.clientX, ev.clientY); });
objectClicked.subscribe(function(o) { ... });
如果你确实需要知道鼠标悬停在哪个对象上,但是想要避免在点击时调用昂贵的命中测试,那么你确实需要存储中间值(无论如何你需要存储它)你的悬停效果)。您可以使用BehaviorSubject
来实现此目的:
this.objectUnderCursor = new Rx.BehaviorSubject();
mouseMoveObservable
.select(function (ev) { return findObject(ev.clientX, ev.clientY); })
.subscribe(this.objectUnderCursor);
this.objectUnderCursor.subscribe(function (o) { do your hover effects here });
mouseClickObservable
.selectMany(function () { return this.objectUnderCursor; })
.subscribe(function (o) { do your click effect });