Skip to content

Interactions: brush #71

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 6 commits into from
Jan 28, 2022
Merged

Interactions: brush #71

merged 6 commits into from
Jan 28, 2022

Conversation

Fil
Copy link
Contributor

@Fil Fil commented Dec 22, 2020

Fixes #5.

TODO

  • Update the plot’s value on interaction, and emit an input event
  • Set the value on the figure when the svg is wrapped (brush facets; target root element #717)
  • Support faceting (either with unioned or exclusive brushes) (brush facets; target root element #717)
  • Allow brush styling (stroke, strokeWidth, strokeOpacity, fill, fillOpacity, etc.)?
  • Decide what happens if multiple marks expose selections: the last one wins (mostly).
  • Disable the standard mark channels (e.g., href, title)? No, just don’t do that.
  • Set the plot’s initial value when there’s no initial selection
  • Improve band scales (select when the band intersects the brush)
  • Support scale insets (use scale ranges rather than chart dimensions)? No, it’s fine as is.
  • A more explicit cue to indicate that a mark exposes a selection (currently node.selection)
  • Set the plot’s initial value when there is an initial selection (what about faceting)? Not yet.
  • Tests (minimal…)
  • Documentation

Previous tests of brush, brushX and brushY: https://observablehq.com/d/2044e02a89cc688a

@Fil
Copy link
Contributor Author

Fil commented Dec 22, 2020

Capture d’écran 2020-12-22 à 18 38 59

Capture d’écran 2020-12-22 à 18 39 59

Capture d’écran 2020-12-22 à 18 39 28

@Fil
Copy link
Contributor Author

Fil commented Dec 23, 2020

Faceting now fully works, including when setting an initial brush selection.
Capture d’écran 2020-12-23 à 13 35 31

Caveat When faceting, the initial brush selection will be applied to 1 facet only—and which one, is arbitrary (it's the first that is created). It might be possible to specify that by passing the facet's "number", but that number is something internal; a solution to this sub-issue (if we want one), should be based on the data.

@Fil
Copy link
Contributor Author

Fil commented Jan 6, 2021

rebased

@Fil
Copy link
Contributor Author

Fil commented Feb 3, 2021

Plot.brush should probably not set the scales’ domains, just take them as they are given. (There is no meaningful way we would brush something we don't see, so setting the scales is going to be done by another mark.)

@mbostock mbostock added this to the Friends Preview milestone Feb 24, 2021
@Fil Fil self-assigned this Mar 3, 2021
@Fil Fil requested a review from mbostock March 9, 2021 15:14
@Fil
Copy link
Contributor Author

Fil commented Mar 9, 2021

By not setting x and y we make sure than this mark does not reserve space for something invisible. So for example if we don't show all the data as dots, we can still use Plot.brush(data) to brush the space.

viewof selection = Plot.plot({marks: [
  Plot.dot(data.filter(d => d[0] > 0), { fill: "2", r: 2.5, stroke: "black", strokeWidth: 0.5 }),
  Plot.brush(data, { selection: [[-2, 2], [0, 0]] })
]})

Fil added a commit that referenced this pull request Mar 10, 2021
- this initial version works on rects
- default picker is d => d (each rect will send its value to the viewof), one can set picker: d => d.x
- picker: null will not set onclick
- bin transforms set picker = group => groupData (aka "the right thing")
- not fully tested with faceting, though it seems to work
- added a general mechanism to send the value as an Input event (not sure it's the right thing to do though), better than the async method of #71
- q: should we always send the initial value, and if so what data? a solution to this problem would be to opt in with a global {picker: data} and the picking would only apply to marks that have the same data.

test https://observablehq.com/d/f4e32e31ec214e38
@mbostock mbostock removed this from the Friends Preview milestone Mar 10, 2021
@mbostock
Copy link
Member

(This is already covered by #5 in the project board and milestone, so I don’t want to list it twice.)

Fil added a commit that referenced this pull request Mar 11, 2021
- this initial version works on rects
- default picker is d => d (each rect will send its value to the viewof), one can set picker: d => d.x
- picker: null will not set onclick
- bin transforms set picker = group => groupData (aka "the right thing")
- not fully tested with faceting, though it seems to work
- added a general mechanism to send the value as an Input event (not sure it's the right thing to do though), better than the async method of #71
- q: should we always send the initial value, and if so what data? a solution to this problem would be to opt in with a global {picker: data} and the picking would only apply to marks that have the same data.

test https://observablehq.com/d/f4e32e31ec214e38
Fil added a commit that referenced this pull request Mar 15, 2021
- this initial version works on rects
- default picker is d => d (each rect will send its value to the viewof), one can set picker: d => d.x
- picker: null will not set onclick
- bin transforms set picker = group => groupData (aka "the right thing")
- not fully tested with faceting, though it seems to work
- added a general mechanism to send the value as an Input event (not sure it's the right thing to do though), better than the async method of #71
- q: should we always send the initial value, and if so what data? a solution to this problem would be to opt in with a global {picker: data} and the picking would only apply to marks that have the same data.

test https://observablehq.com/d/f4e32e31ec214e38
@Fil
Copy link
Contributor Author

Fil commented Mar 30, 2021

We can also brush on ordinal scales.

@Fil Fil changed the title brush Interactions: brush May 1, 2021
@nami868
Copy link

nami868 commented Nov 17, 2021

@Fil My demo report error TypeError: Plot.brush is not a function. How do i fix it? Thanks..

@Fil
Copy link
Contributor Author

Fil commented Nov 17, 2021

@nami868 are you using a build that includes this code? Plot.brush is not part of the official distribution, it only lives on this development branch. See https://observablehq.com/@fil/plot-early-bird

@nami868
Copy link

nami868 commented Nov 17, 2021

@nami868 are you using a build that includes this code? Plot.brush is not part of the official distribution, it only lives on this development branch. See https://observablehq.com/@fil/plot-early-bird

thanks

Fil added a commit that referenced this pull request Jan 15, 2022
* internal selection boolean channel & dataflow
* internal dispatch
* clickable option on dots and rules
* merge #71
* onchange handler
* marks always have a nodes property and share a default select function which hides/shows the children
* facets: when using faceted brushes, clicking on a brush cancels the others; and a programmatic selection cancels all the brushes
@Fil Fil mentioned this pull request Jan 15, 2022
@Fil Fil deleted the brush branch January 16, 2022 11:33
@mbostock mbostock assigned mbostock and unassigned Fil Jan 22, 2022
@mbostock mbostock restored the brush branch January 22, 2022 04:09
@mbostock mbostock reopened this Jan 22, 2022
@mbostock
Copy link
Member

I think this is close. I want to try resurrecting this branch, making a few tweaks, and thinking about the ownerSVGElement problem. We can keep thinking about the selection channel in #669 but we may be able to land brushing (and perhaps pointing? or lasso?) ahead of that.

@mbostock
Copy link
Member

Idle musing: I wonder if marks could emit events?

Also: When brushing with faceting, I could imagine a mode where you can have multiple brushes active, and the selection is the union across facets.

@mbostock mbostock force-pushed the brush branch 4 times, most recently from bf140b8 to 3c12b39 Compare January 28, 2022 20:20
Co-authored-by: Mike Bostock <[email protected]>
@mbostock
Copy link
Member

Okay, I think this is ready to go @Fil. It’s missing the ability to set the initial selection, but I think this is still a fine starting point.

Copy link
Member

@mbostock mbostock left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LG! Fil, since you opened this, can you just comment on whether you approve?

@Fil
Copy link
Contributor Author

Fil commented Jan 28, 2022

Yes! 🚀

@mbostock mbostock merged commit 5ce6cc0 into main Jan 28, 2022
@mbostock mbostock deleted the brush branch January 28, 2022 22:29
This was referenced Feb 9, 2022
@mishatsvelik
Copy link

Regarding faceting, how about supporting an option which synchronises the brush area across all facets? Why is this useful? For example lets say we have plot.line faceted and we use brush.x to select points of comparison between the right-most point in the brush area vs the left most point let's say these are dates in a time-series

@Fil
Copy link
Contributor Author

Fil commented May 25, 2023

@Fil Fil mentioned this pull request May 29, 2023
25 tasks
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Brushing
4 participants