0

我正在尝试基于另外两个创建新的 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 })

但它一键生成多个值

4

1 回答 1

0

我没有看到您实际订阅您定义的任何这些可观察对象的任何代码,因此很难提供一个好的答案。你真的需要调用findObject每一个鼠标移动吗?您是否需要在鼠标移动时提供某种悬停效果?或者你只需​​要知道被点击的对象,在这种情况下你只需要findObject在点击时调用一次?

假设您只需要知道单击了哪个对象,您甚至不必担心鼠标移动,只需执行以下操作:

var objectClicked = mouseClickObservable
    .select(function (ev) { return findObject(ev.clientX, ev.clientY); });

objectClicked.subscribe(function(o) { ... });

如果您确实需要知道鼠标悬停在哪个对象上,但又想避免在单击时调用昂贵的命中测试,那么您确实需要存储中间值(无论如何您都需要存储它来执行悬停效果)。您可以BehaviorSubject为此目的使用 a:

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 });
于 2013-07-15T17:32:36.983 回答