I have a stack of cards with bounds { x, y, w, h } stacked on top of each other with some offset y value.
I am trying to implement click events on this cards. So I have a click event stream on document as such:
let starts = fromEvent(document, 'mousedown'),
ends = fromEvent(document, 'mouseup');
starts = starts.map(e => {
let epos = eventPosition(e);
return {
start: epos,
epos
};
});
ends = ends.map(e => {
return {
epos: eventPosition(e)
};
});
let clicks = starts.flatMap(startE => {
return ends.first()
.takeUntil(later(600));
});
function Card(n) {
// inHitBounds returns true when event position is within the cards bounds.
let inHitBounds = _ => hitTest(..._.epos, container.bounds());
let insertN = _ => ({ ..._, n });
// returns a stream which emits a card click event whenever it is in bounds of this card.
this.clicks = clicks.filter(inHitBounds).map(insertN);
}
function CardStack(stack) {
let dCards = stack.map(n => new Card(n));
// returns a stream which emits a card click event with the upper most card that is clicked.
this.clicks = ???
// I tried this but it failed:
this.clicks = dCards
.map(_ => _.clicks)
.reduce((acc, _) => acc.merge(_), Bacon.never)
.first();
}
there's actually a method Bacon.groupSimultaneous which lets you group "simultaneous" events from multiple sources. I wrote an example: https://codesandbox.io/s/groupsimultaneous-example-cdthp
So you can group events from your cards and from a group of events select the one which represents the topmost card.
Just realized that this method is excluded from the API docs at https://baconjs.github.io/api3/globals.html
Otherwise you might rethink a bit and create a stream that listens to clicks
and then, based on the dCards
array, picks the topmost card which intersects with the click pos.