0

J'essaie de créer de nouveaux observables basés sur deux autres. J'ai:Joindre deux observables dans RX.js

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); 
}); 

Je veux créer objectClicked observable, qui devrait produire des valeurs lorsque l'utilisateur clique sur un objet. Je pourrais simplement appeler findObject à nouveau, comme ceci:

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

mais il est très fonction du temps.

Une autre façon, que j'utilise actuellement, est de stocker le dernier objet survolé dans une variable, mais je suppose qu'il devrait y avoir une manière purement fonctionnelle de le faire. J'ai essayé d'utiliser Observable.join comme ceci:

var objectClicked = this.objectUnderCursor.join(
    mouseClickObservable, 
    function (obj) { return this.objectUnderCursor }, 
    function (ev) { return Rx.Observable.empty() }, 
    function (obj, ev) { return obj }) 

mais il produit plusieurs valeurs pour un seul clic

Répondre

0

Je ne vois pas de code où vous avez réellement abonnez à l'une de ces observables que vous avez définis , il est donc difficile de fournir une bonne réponse. Avez-vous réellement besoin d'appeler le findObject à chaque mouvement de la souris? Avez-vous besoin de fournir une sorte d'effet de survol lorsque la souris se déplace? Ou avez-vous juste besoin de connaître l'objet sur lequel vous avez cliqué, auquel cas vous n'avez besoin d'appeler qu'une seule fois le findObject?

En supposant que vous avez seulement besoin de savoir quel objet vous avez cliqué, ne vous inquiétez même pas la souris se déplace et faire quelque chose comme:

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

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

Si vous avez besoin en effet de savoir quel objet la souris est en vol stationnaire au-dessus de , mais vous voulez éviter d'appeler votre test de hit coûteux aussi sur un clic, alors en effet vous devez stocker la valeur intermédiaire (que vous avez besoin de stocker de toute façon pour faire vos effets de vol stationnaire). Vous pouvez utiliser un BehaviorSubject à cet effet:

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 }); 
+0

Oui, je dois savoir ce que la souris est en vol stationnaire, et votre dernière solution a été très utile, mais observable créé par '.selectMany (function() {return this.objectUnderCursor ;}) 'continuera à produire des valeurs lorsque la souris se déplace après le clic. Je l'ai changé en '.selectMany (function() {return this.objectUnderCursor.first();})' et cela fonctionne parfaitement. Merci beaucoup! –