You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Copy file name to clipboardExpand all lines: docs/interactions/brush.md
+20-24Lines changed: 20 additions & 24 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -80,7 +80,7 @@ Similarly, the **brushY** mark operates on the *y* axis.
80
80
81
81
## Input events
82
82
83
-
The brush dispatches an [*input* event](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event) whenever the selection changes. The plot’s value (`plot.value`) is set to a [BrushValue](#brushvalue) object when a selection is active, or null when the selection is cleared. This allows you to use a plot as an [Observable view](https://observablehq.com/@observablehq/views), or to register an *input* event listener to react to the brush.
83
+
The brush dispatches an [*input* event](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/input_event) whenever the selection changes. The plot’s value (`plot.value`) is set to a [Region](#region) instance when a selection is active, or null when the selection is cleared. This allows you to use a plot as an [Observable view](https://observablehq.com/@observablehq/views), or to register an *input* event listener to react to the brush.
The **filter**function on the brush value tests whether a data point falls inside the selection. Its signature depends on whether the plot uses faceting, and on the brush’s dimension:
93
+
The **contains**method on the region tests whether a data point falls inside the selection:
|**fx** only |*filter*(*value*, *fx*) |*filter*(*x*, *y*, *fx*) |
99
-
|**fy** only |*filter*(*value*, *fy*) |*filter*(*x*, *y*, *fy*) |
100
-
|**fx** and **fy**|*filter*(*value*, *fx*, *fy*) |*filter*(*x*, *y*, *fx*, *fy*) |
95
+
- 2-D brush: *region*.contains(*x*, *y*) or *region*.contains(*x*, *y*, {*fx*, *fy*})
96
+
- 1-D brush: *region*.contains(*value*) or *region*.contains(*value*, {*fx*}) / *region*.contains(*value*, {*fy*})
97
+
98
+
For faceted plots, you can optionally pass the facet values as an object; contains then returns true only for points in the brushed facet. For example:
constselected= region ?penguins.filter((d) =>region.contains(d.culmen_length_mm, d.culmen_depth_mm)) : penguins;
108
104
console.log(selected);
109
105
});
110
106
```
111
107
112
-
The facet arguments are optional: if *fx* or *fy* is undefined, the filter skips the facet check for that dimension. For example, if the selected region is [44, 46] × [17, 19] over the "Adelie" facet:
108
+
The facet argument is optional: if omitted, contains skips the facet check. For example, if the selected region is [44, 46]×[17, 19] over the "Adelie" facet:
113
109
114
110
```js
115
-
constfilter=plot.value?.filter; // f(x, y, fx)
116
-
filter(45, 18) // true
117
-
filter(45, 18, "Adelie") // true
118
-
filter(45, 18, "Gentoo") // false
111
+
const{contains}=plot.value;
112
+
contains(45, 18) // true
113
+
contains(45, 18, {fx:"Adelie"}) // true
114
+
contains(45, 18, {fx:"Gentoo"}) // false
119
115
```
120
116
121
117
## Reactive marks
@@ -159,7 +155,7 @@ To achieve higher contrast, you can place the brush before the reactive marks; r
159
155
160
156
## Faceting
161
157
162
-
The brush mark supports [faceting](../features/facets.md). When the plot uses **fx** or **fy** facets, each facet gets its own brush. The dispatched value includes the **fx** and **fy** facet values of the brushed facet, and the **filter** function also filters on the relevant facet values.
158
+
The brush mark supports [faceting](../features/facets.md). When the plot uses **fx** or **fy** facets, each facet gets its own brush. The dispatched value includes the **fx** and **fy** facet values of the brushed facet; optionally pass `{fx, fy}` as the last argument to **contains**to restrict matching to the brushed facet.
163
159
164
160
:::plot hidden
165
161
```js
@@ -225,7 +221,7 @@ The dispatched value still includes **fx** (and **fy**), indicating the facet wh
225
221
226
222
## Projections
227
223
228
-
For plots with a [geographic projection](../features/projections.md), the brush operates in screen space. The brush value’s **x1**, **y1**, **x2**, **y2** bounds are expressed in pixels from the top-left corner of the frame, and the **filter** function takes the data's coordinates (typically longitude and latitude) and projects them to test against the brush extent.
224
+
For plots with a [geographic projection](../features/projections.md), the brush operates in screen space. The brush value’s **x1**, **y1**, **x2**, **y2** bounds are expressed in pixels from the top-left corner of the frame. Use **contains**with pixel coordinates to test against the brush extent.
229
225
230
226
<divv-if="land && cities.length">
231
227
@@ -262,17 +258,17 @@ Plot.plot({
262
258
})
263
259
```
264
260
265
-
## BrushValue {#brushvalue}
261
+
## Region {#region}
266
262
267
-
The brush value dispatched on [_input_ events](#input-events). When the brush is cleared, the value is null; otherwise it's an object with the following properties:
263
+
The brush value dispatched on [_input_ events](#input-events). When the brush is cleared, the value is null; otherwise it's a `Region` instance with the following properties:
268
264
269
265
-**x1** - the lower *x* bound of the selection (in data space, or pixels if projected)
270
266
-**x2** - the upper *x* bound of the selection
271
267
-**y1** - the lower *y* bound of the selection
272
268
-**y2** - the upper *y* bound of the selection
273
269
-**fx** - the *fx* facet value, if applicable
274
270
-**fy** - the *fy* facet value, if applicable
275
-
- **filter** - a function to test whether a point is inside the selection
271
+
-**contains** - a method to test whether a point is inside the selection; see [input events](#input-events)
276
272
-**pending** - `true` during interaction; absent when committed
277
273
278
274
By convention, *x1* < *x2* and *y1* < *y2*. The brushX value does not include *y1* and *y2*; similarly, the brushY value does not include *x1* and *x2*. Values are automatically rounded to the optimal precision that distinguishes neighboring pixels.
For projected plots, the coordinates are in pixels (consistent with the [BrushValue](#brushvalue)), so you need to project the two corners of the brush beforehand. In the future Plot might expose its *projection* to facilitate this. Please upvote [this issue](https://github.com/observablehq/plot/issues/1191) to help prioritize this feature.
341
+
For projected plots, the coordinates are in pixels (consistent with the [Region](#region)), so you need to project the two corners of the brush beforehand. In the future Plot might expose its *projection* to facilitate this. Please upvote [this issue](https://github.com/observablehq/plot/issues/1191) to help prioritize this feature.
346
342
347
343
## brushX(*options*) {#brushX}
348
344
@@ -354,7 +350,7 @@ Returns a new horizontal brush mark that selects along the *x* axis. The availab
354
350
355
351
- **interval** - an interval to snap the brush to on release; a number for quantitative scales (_e.g._, `100`), a time interval name for temporal scales (_e.g._, `"month"`), or an object with *floor* and *offset* methods
356
352
357
-
When an **interval** is set, the selection snaps to interval boundaries on release, and the filter rounds values before testing, for consistency with binned marks using the same interval. (Use the same interval in the bin transform so the brush aligns with bin edges.)
353
+
When an **interval** is set, the selection snaps to interval boundaries on release. (Use the same interval in the bin transform so the brush aligns with bin edges.)
0 commit comments