mark.initialize · Salebarn/plot@43e482c · GitHub
Skip to content

Commit 43e482c

Browse files
committed
mark.initialize
1 parent cf40055 commit 43e482c

16 files changed

Lines changed: 207 additions & 226 deletions

File tree

src/mark.js

Lines changed: 16 additions & 17 deletions

src/marks/area.js

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {create} from "d3-selection";
22
import {area as shapeArea} from "d3-shape";
33
import {Curve} from "../curve.js";
4-
import {identity, indexOf, zero} from "../mark.js";
4+
import {identity, indexOf, zero, string, number} from "../mark.js";
55
import {defined} from "../defined.js";
66
import {Mark} from "../mark.js";
77

@@ -30,22 +30,14 @@ export class Area extends Mark {
3030
]
3131
);
3232
this.curve = Curve(curve);
33-
this.fill = fill;
34-
this.fillOpacity = fillOpacity;
33+
this.fill = string(fill);
34+
this.fillOpacity = number(fillOpacity);
3535
}
36-
render(I, {x: {scale: x}, y: {scale: y}}) {
37-
const {
38-
curve,
39-
channels: {
40-
x1: {value: X1},
41-
y1: {value: Y1},
42-
x2: {value: X2} = {value: X1},
43-
y2: {value: Y2} = {value: Y1}
44-
}
45-
} = this;
36+
render(I, {x, y}, {x1: X1, y1: Y1, x2: X2 = X1, y2: Y2 = Y1}) {
37+
const {curve, fill, fillOpacity} = this;
4638
return create("svg:path")
47-
.attr("fill", this.fill)
48-
.attr("fill-opacity", this.fillOpacity)
39+
.attr("fill", fill)
40+
.attr("fill-opacity", fillOpacity)
4941
.attr("d", shapeArea()
5042
.curve(curve)
5143
.defined(i => defined(X1[i]) && defined(Y1[i]) && defined(X2[i]) && defined(Y2[i]))

src/marks/axis.js

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,8 +23,9 @@ export class AxisX {
2323
this.labelOffset = labelOffset;
2424
}
2525
render(
26-
_,
27-
{x: {scale: x}},
26+
index,
27+
{x},
28+
channels,
2829
{width, height, marginTop, marginRight, marginBottom, marginLeft}
2930
) {
3031
const {
@@ -87,8 +88,9 @@ export class AxisY {
8788
this.labelOffset = labelOffset;
8889
}
8990
render(
90-
_,
91-
{y: {scale: y}},
91+
index,
92+
{y},
93+
channels,
9294
{width, height, marginTop, marginRight, marginBottom, marginLeft}
9395
) {
9496
const {

src/marks/bar.js

Lines changed: 32 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {create} from "d3-selection";
22
import {identity, indexOf} from "../mark.js";
33
import {defined} from "../defined.js";
4-
import {Mark} from "../mark.js";
4+
import {Mark, string, number} from "../mark.js";
55

66
class Bar extends Mark {
77
constructor(
@@ -21,29 +21,26 @@ class Bar extends Mark {
2121
} = {}
2222
) {
2323
super(data, channels);
24-
this.fill = fill;
25-
this.fillOpacity = fillOpacity;
26-
this.stroke = stroke;
27-
this.strokeWidth = strokeWidth;
28-
this.strokeOpacity = strokeOpacity;
29-
this.mixBlendMode = mixBlendMode;
30-
this.insetTop = insetTop;
31-
this.insetRight = insetRight;
32-
this.insetBottom = insetBottom;
33-
this.insetLeft = insetLeft;
24+
this.fill = string(fill);
25+
this.fillOpacity = number(fillOpacity);
26+
this.stroke = string(stroke);
27+
this.strokeWidth = number(strokeWidth);
28+
this.strokeOpacity = number(strokeOpacity);
29+
this.mixBlendMode = string(mixBlendMode);
30+
this.insetTop = number(insetTop);
31+
this.insetRight = number(insetRight);
32+
this.insetBottom = number(insetBottom);
33+
this.insetLeft = number(insetLeft);
3434
}
35-
render(I, scales) {
35+
render(I, scales, channels) {
36+
const {x: X, y: Y} = channels;
3637
const {
3738
fill,
3839
fillOpacity,
3940
stroke,
4041
strokeWidth,
4142
strokeOpacity,
42-
mixBlendMode,
43-
channels: {
44-
x: {value: X},
45-
y: {value: Y}
46-
}
43+
mixBlendMode
4744
} = this;
4845
return create("svg:g")
4946
.attr("fill", fill)
@@ -55,10 +52,10 @@ class Bar extends Mark {
5552
.data(I.filter(i => defined(X[i]) && defined(Y[i])))
5653
.join("rect")
5754
.style("mix-blend-mode", mixBlendMode)
58-
.attr("x", this._x(scales))
59-
.attr("width", this._width(scales))
60-
.attr("y", this._y(scales))
61-
.attr("height", this._height(scales)))
55+
.attr("x", this._x(scales, channels))
56+
.attr("width", this._width(scales, channels))
57+
.attr("y", this._y(scales, channels))
58+
.attr("height", this._height(scales, channels)))
6259
.node();
6360
}
6461
}
@@ -75,19 +72,19 @@ export class BarX extends Bar {
7572
style
7673
);
7774
}
78-
_x({x: {scale: x}}) {
79-
const {insetLeft, channels: {x: {value: X}}} = this;
75+
_x({x}, {x: X}) {
76+
const {insetLeft} = this;
8077
return i => Math.min(x(0), x(X[i])) + insetLeft;
8178
}
82-
_y({y: {scale: y}}) {
83-
const {insetTop, channels: {y: {value: Y}}} = this;
79+
_y({y}, {y: Y}) {
80+
const {insetTop} = this;
8481
return i => y(Y[i]) + insetTop;
8582
}
86-
_width({x: {scale: x}}) {
87-
const {insetLeft, insetRight, channels: {x: {value: X}}} = this;
83+
_width({x}, {x: X}) {
84+
const {insetLeft, insetRight} = this;
8885
return i => Math.max(0, Math.abs(x(X[i]) - x(0)) - insetLeft - insetRight);
8986
}
90-
_height({y: {scale: y}}) {
87+
_height({y}) {
9188
const {insetTop, insetBottom} = this;
9289
return Math.max(0, y.bandwidth() - insetTop - insetBottom);
9390
}
@@ -105,20 +102,20 @@ export class BarY extends Bar {
105102
style
106103
);
107104
}
108-
_x({x: {scale: x}}) {
109-
const {insetLeft, channels: {x: {value: X}}} = this;
105+
_x({x}, {x: X}) {
106+
const {insetLeft} = this;
110107
return i => x(X[i]) + insetLeft;
111108
}
112-
_y({y: {scale: y}}) {
113-
const {insetTop, channels: {y: {value: Y}}} = this;
109+
_y({y}, {y: Y}) {
110+
const {insetTop} = this;
114111
return i => Math.min(y(0), y(Y[i])) + insetTop;
115112
}
116-
_width({x: {scale: x}}) {
113+
_width({x}) {
117114
const {insetLeft, insetRight} = this;
118115
return Math.max(0, x.bandwidth() - insetLeft - insetRight);
119116
}
120-
_height({y: {scale: y}}) {
121-
const {insetTop, insetBottom, channels: {y: {value: Y}}} = this;
117+
_height({y}, {y: Y}) {
118+
const {insetTop, insetBottom} = this;
122119
return i => Math.max(0, Math.abs(y(0) - y(Y[i])) - insetTop - insetBottom);
123120
}
124121
}

src/marks/bin.js

Lines changed: 33 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,48 @@
1-
import {bin as Bin} from "d3-array";
2-
import {field, identity} from "../mark.js";
3-
import {rectX, rectY} from "./rect.js";
1+
import {bin} from "d3-array";
2+
import {field, identity, zero} from "../mark.js";
3+
import {Rect} from "./rect.js";
4+
5+
export class Bin extends Rect {
6+
constructor(data, {value, ...channels}, style) {
7+
super(data, channels, style);
8+
this.value = value;
9+
}
10+
facet({y}) {
11+
return bins(this.data, this.value, y);
12+
}
13+
}
414

515
export function binX(data, {x = identity} = {}, style) {
6-
return rectX(
7-
bin(data, x), // TODO configurable thresholds
8-
{y1: typeof x === "string" ? startof(x) : start, y2: end, x: length},
16+
return new Bin(
17+
data,
18+
{
19+
x1: zero,
20+
y1: typeof x === "string" ? startof(x) : start,
21+
x2: length,
22+
y2: end
23+
},
924
{insetTop: 1, ...style}
1025
);
1126
}
1227

1328
export function binY(data, {y = identity} = {}, style) {
14-
return rectY(
15-
bin(data, y), // TODO configurable thresholds
16-
{x1: typeof y === "string" ? startof(y) : start, x2: end, y: length},
29+
return new Bin(
30+
data,
31+
{
32+
x1: typeof y === "string" ? startof(y) : start,
33+
y1: zero,
34+
x2: end,
35+
y2: length
36+
},
1737
{insetLeft: 1, ...style}
1838
);
1939
}
2040

21-
function bin(data, value) {
41+
// TODO configurable thresholds
42+
// TODO facet dimension
43+
function bins(data, value) {
2244
if (typeof value === "string") value = field(value);
23-
return Bin().value(value)(data);
45+
return bin().value(value)(data);
2446
}
2547

2648
function startof(value) {

src/marks/dot.js

Lines changed: 11 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import {ascending} from "d3-array";
22
import {create} from "d3-selection";
33
import {defined} from "../defined.js";
4-
import {Mark, indexOf, identity} from "../mark.js";
4+
import {Mark, indexOf, identity, string, number} from "../mark.js";
55

66
const first = d => d[0];
77
const second = d => d[1];
@@ -38,38 +38,26 @@ export class Dot extends Mark {
3838
{name: "stroke", value: stroke, scale: "color", optional: true}
3939
]
4040
);
41-
this.r = fixedR;
42-
this.fill = fixedFill;
43-
this.fillOpacity = fillOpacity;
44-
this.stroke = fixedStroke;
45-
this.strokeWidth = strokeWidth;
46-
this.strokeOpacity = strokeOpacity;
47-
this.mixBlendMode = mixBlendMode;
41+
this.r = number(fixedR);
42+
this.fill = string(fixedFill);
43+
this.fillOpacity = number(fillOpacity);
44+
this.stroke = string(fixedStroke);
45+
this.strokeWidth = number(strokeWidth);
46+
this.strokeOpacity = number(strokeOpacity);
47+
this.mixBlendMode = string(mixBlendMode);
4848
}
4949
render(
5050
I,
51-
{
52-
x: {scale: x},
53-
y: {scale: y},
54-
r: {scale: r} = {},
55-
color: {scale: color} = {}
56-
}
51+
{x, y, r, color},
52+
{x: X, y: Y, z: Z, r: R, fill: F, stroke: S}
5753
) {
5854
const {
5955
fill,
6056
fillOpacity,
6157
stroke,
6258
strokeWidth,
6359
strokeOpacity,
64-
mixBlendMode,
65-
channels: {
66-
x: {value: X},
67-
y: {value: Y},
68-
z: {value: Z} = {},
69-
r: {value: R} = {},
70-
fill: {value: F} = {},
71-
stroke: {value: S} = {}
72-
}
60+
mixBlendMode
7361
} = this;
7462
const index = I.filter(i => defined(X[i]) && defined(Y[i]));
7563
if (Z) index.sort((i, j) => ascending(Z[i], Z[j]));

src/marks/facet.js

Lines changed: 12 additions & 6 deletions

0 commit comments

Comments
 (0)