Skip to content

Commit cec9a01

Browse files
committed
brush
closes #5
1 parent 5385b8d commit cec9a01

File tree

4 files changed

+130
-1
lines changed

4 files changed

+130
-1
lines changed

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
"dependencies": {
3636
"d3-array": "^2.8.0",
3737
"d3-axis": "^2.0.0",
38+
"d3-brush": "^2.0.0",
3839
"d3-color": "^2.0.0",
3940
"d3-interpolate": "^2.0.1",
4041
"d3-scale": "^3.2.3",

src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ export {Area, area, areaX, areaY} from "./marks/area.js";
44
export {AxisX, AxisY} from "./marks/axis.js";
55
export {BarX, BarY, barX, barY} from "./marks/bar.js";
66
export {bin, binX, binY} from "./marks/bin.js";
7+
export {brush, brushX, brushY} from "./marks/brush.js";
78
export {Cell, cell, cellX, cellY} from "./marks/cell.js";
89
export {Dot, dot, dotX, dotY} from "./marks/dot.js";
910
export {group, groupX, groupY} from "./marks/group.js";

src/marks/brush.js

Lines changed: 82 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,82 @@
1+
import {extent} from "d3-array";
2+
import {brush as brusher, brushX as brusherX, brushY as brusherY} from "d3-brush";
3+
import {create} from "d3-selection";
4+
import {filter} from "../defined.js";
5+
import {Mark, identity, first, second} from "../mark.js";
6+
import {Style} from "../style.js";
7+
8+
export class Brush extends Mark {
9+
constructor(
10+
data,
11+
{
12+
x = first,
13+
y = second,
14+
transform,
15+
...style
16+
} = {}
17+
) {
18+
super(
19+
data,
20+
[
21+
{name: "x", value: x, scale: "x", optional: true},
22+
{name: "y", value: y, scale: "y", optional: true}
23+
],
24+
transform
25+
);
26+
Style(this, style);
27+
}
28+
render(
29+
I,
30+
{x, y},
31+
{x: X, y: Y},
32+
{marginLeft, width, marginRight, marginTop, height, marginBottom}
33+
) {
34+
const g = create("svg:g");
35+
36+
const brush = (x && y ? brusher : x ? brusherX : brusherY)()
37+
.extent([
38+
[marginLeft, marginTop],
39+
[width - marginRight, height - marginBottom]
40+
])
41+
.on("start brush end", ({ selection }) => {
42+
let index = filter(I, X, Y);
43+
if (selection) {
44+
if (x) {
45+
const e = y ? [selection[0][0], selection[1][0]] : selection;
46+
const [x0, x1] = extent(e.map(x.invert));
47+
index = index.filter(i => X[i] >= x0 && X[i] < x1);
48+
}
49+
if (y) {
50+
const e = x ? [selection[0][1], selection[1][1]] : selection;
51+
const [y0, y1] = extent(e.map(y.invert));
52+
index = index.filter(i => Y[i] >= y0 && Y[i] < y1);
53+
}
54+
}
55+
56+
const dots = Array.from(index, i => this.data[i]);
57+
58+
const parent = g.node().ownerSVGElement;
59+
parent.value = dots;
60+
parent.dispatchEvent(new CustomEvent('input'));
61+
});
62+
63+
g.call(brush);
64+
65+
/* 🌶 async (wait for the ownerSVGElement to send the first signal) */
66+
setTimeout(() => g.call(brush.clear), 1);
67+
68+
return g.node();
69+
}
70+
}
71+
72+
export function brush(data, options) {
73+
return new Brush(data, options);
74+
}
75+
76+
export function brushX(data, {x = identity, ...options} = {}) {
77+
return new Brush(data, {...options, x, y: null});
78+
}
79+
80+
export function brushY(data, {y = identity, ...options} = {}) {
81+
return new Brush(data, {...options, x: null, y});
82+
}

yarn.lock

Lines changed: 46 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -297,11 +297,40 @@ d3-axis@^2.0.0:
297297
resolved "https://registry.yarnpkg.com/d3-axis/-/d3-axis-2.0.0.tgz#40aebb65626ffe6d95e9441fbf9194274b328a8b"
298298
integrity sha512-9nzB0uePtb+u9+dWir+HTuEAKJOEUYJoEwbJPsZ1B4K3iZUgzJcSENQ05Nj7S4CIfbZZ8/jQGoUzGKFznBhiiQ==
299299

300+
d3-brush@^2.0.0:
301+
version "2.1.0"
302+
resolved "https://registry.yarnpkg.com/d3-brush/-/d3-brush-2.1.0.tgz#adadfbb104e8937af142e9a6e2028326f0471065"
303+
integrity sha512-cHLLAFatBATyIKqZOkk/mDHUbzne2B3ZwxkzMHvFTCZCmLaXDpZRihQSn8UNXTkGD/3lb/W2sQz0etAftmHMJQ==
304+
dependencies:
305+
d3-dispatch "1 - 2"
306+
d3-drag "2"
307+
d3-interpolate "1 - 2"
308+
d3-selection "2"
309+
d3-transition "2"
310+
300311
"d3-color@1 - 2", d3-color@^2.0.0:
301312
version "2.0.0"
302313
resolved "https://registry.yarnpkg.com/d3-color/-/d3-color-2.0.0.tgz#8d625cab42ed9b8f601a1760a389f7ea9189d62e"
303314
integrity sha512-SPXi0TSKPD4g9tw0NMZFnR95XVgUZiBH+uUTqQuDu1OsE2zomHU7ho0FISciaPvosimixwHFl3WHLGabv6dDgQ==
304315

316+
"d3-dispatch@1 - 2":
317+
version "2.0.0"
318+
resolved "https://registry.yarnpkg.com/d3-dispatch/-/d3-dispatch-2.0.0.tgz#8a18e16f76dd3fcaef42163c97b926aa9b55e7cf"
319+
integrity sha512-S/m2VsXI7gAti2pBoLClFFTMOO1HTtT0j99AuXLoGFKO6deHDdnv6ZGTxSTTUTgO1zVcv82fCOtDjYK4EECmWA==
320+
321+
d3-drag@2:
322+
version "2.0.0"
323+
resolved "https://registry.yarnpkg.com/d3-drag/-/d3-drag-2.0.0.tgz#9eaf046ce9ed1c25c88661911c1d5a4d8eb7ea6d"
324+
integrity sha512-g9y9WbMnF5uqB9qKqwIIa/921RYWzlUDv9Jl1/yONQwxbOfszAWTCm8u7HOTgJgRDXiRZN56cHT9pd24dmXs8w==
325+
dependencies:
326+
d3-dispatch "1 - 2"
327+
d3-selection "2"
328+
329+
"d3-ease@1 - 2":
330+
version "2.0.0"
331+
resolved "https://registry.yarnpkg.com/d3-ease/-/d3-ease-2.0.0.tgz#fd1762bfca00dae4bacea504b1d628ff290ac563"
332+
integrity sha512-68/n9JWarxXkOWMshcT5IcjbB+agblQUaIsbnXmrzejn2O82n3p2A9R2zEB9HIEFWKFwPAEDDN8gR0VdSAyyAQ==
333+
305334
"d3-format@1 - 2":
306335
version "2.0.0"
307336
resolved "https://registry.yarnpkg.com/d3-format/-/d3-format-2.0.0.tgz#a10bcc0f986c372b729ba447382413aabf5b0767"
@@ -338,7 +367,7 @@ d3-scale@^3.2.3:
338367
d3-time "1 - 2"
339368
d3-time-format "2 - 3"
340369

341-
d3-selection@^2.0.0:
370+
d3-selection@2, d3-selection@^2.0.0:
342371
version "2.0.0"
343372
resolved "https://registry.yarnpkg.com/d3-selection/-/d3-selection-2.0.0.tgz#94a11638ea2141b7565f883780dabc7ef6a61066"
344373
integrity sha512-XoGGqhLUN/W14NmaqcO/bb1nqjDAw5WtSYb2X8wiuQWvSZUsUVYsOSkOybUrNvcBjaywBdYPy03eXHMXjk9nZA==
@@ -362,6 +391,22 @@ d3-shape@^2.0.0:
362391
resolved "https://registry.yarnpkg.com/d3-time/-/d3-time-2.0.0.tgz#ad7c127d17c67bd57a4c61f3eaecb81108b1e0ab"
363392
integrity sha512-2mvhstTFcMvwStWd9Tj3e6CEqtOivtD8AUiHT8ido/xmzrI9ijrUUihZ6nHuf/vsScRBonagOdj0Vv+SEL5G3Q==
364393

394+
"d3-timer@1 - 2":
395+
version "2.0.0"
396+
resolved "https://registry.yarnpkg.com/d3-timer/-/d3-timer-2.0.0.tgz#055edb1d170cfe31ab2da8968deee940b56623e6"
397+
integrity sha512-TO4VLh0/420Y/9dO3+f9abDEFYeCUr2WZRlxJvbp4HPTQcSylXNiL6yZa9FIUvV1yRiFufl1bszTCLDqv9PWNA==
398+
399+
d3-transition@2:
400+
version "2.0.0"
401+
resolved "https://registry.yarnpkg.com/d3-transition/-/d3-transition-2.0.0.tgz#366ef70c22ef88d1e34105f507516991a291c94c"
402+
integrity sha512-42ltAGgJesfQE3u9LuuBHNbGrI/AJjNL2OAUdclE70UE6Vy239GCBEYD38uBPoLeNsOhFStGpPI0BAOV+HMxog==
403+
dependencies:
404+
d3-color "1 - 2"
405+
d3-dispatch "1 - 2"
406+
d3-ease "1 - 2"
407+
d3-interpolate "1 - 2"
408+
d3-timer "1 - 2"
409+
365410
dashdash@^1.12.0:
366411
version "1.14.1"
367412
resolved "https://registry.yarnpkg.com/dashdash/-/dashdash-1.14.1.tgz#853cfa0f7cbe2fed5de20326b8dd581035f6e2f0"

0 commit comments

Comments
 (0)