Skip to content

Commit

Permalink
Drop the z channel for bar, dot, link, rect, rule, text, and tick. (o…
Browse files Browse the repository at this point in the history
…bservablehq#345)

* less z

* simpler

* in these 3 examples the z-index has no visual consequence since the marks don't overlap

* simpler

Co-authored-by: Philippe Rivière <[email protected]>
  • Loading branch information
mbostock and Fil authored Apr 30, 2021
1 parent b2d1553 commit 559dd81
Show file tree
Hide file tree
Showing 26 changed files with 925 additions and 1,032 deletions.
13 changes: 10 additions & 3 deletions src/mark.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@ export class Mark {
constructor(data, channels = [], options = {}) {
const names = new Set();
this.data = data;
this.transform = maybeTransform(options);
const {transform} = maybeTransform(options);
this.transform = transform;
this.channels = channels.filter(channel => {
const {name, value, optional} = channel;
if (value == null) {
Expand Down Expand Up @@ -220,13 +221,19 @@ export function maybeLazyChannel(source) {

// If both t1 and t2 are defined, returns a composite transform that first
// applies t1 and then applies t2.
export function maybeTransform({filter: f1, sort: s1, reverse: r1, transform: t1} = {}, t2) {
export function maybeTransform({
filter: f1,
sort: s1,
reverse: r1,
transform: t1,
...options
} = {}, t2) {
if (t1 === undefined) {
if (f1 != null) t1 = filter(f1);
if (s1 != null) t1 = compose(t1, sort(s1));
if (r1) t1 = compose(t1, reverse);
}
return compose(t1, t2);
return {...options, transform: compose(t1, t2)};
}

// Assuming that both x1 and x2 and lazy channels (per above), this derives a
Expand Down
6 changes: 1 addition & 5 deletions src/marks/bar.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import {ascending} from "d3";
import {create} from "d3";
import {filter} from "../defined.js";
import {Mark, number, maybeColor, maybeZero, title, maybeNumber} from "../mark.js";
Expand All @@ -9,7 +8,6 @@ export class AbstractBar extends Mark {
data,
channels,
{
z,
title,
fill,
fillOpacity,
Expand All @@ -33,7 +31,6 @@ export class AbstractBar extends Mark {
data,
[
...channels,
{name: "z", value: z, optional: true},
{name: "title", value: title, optional: true},
{name: "fill", value: vfill, scale: "color", optional: true},
{name: "fillOpacity", value: vfillOpacity, scale: "opacity", optional: true},
Expand All @@ -58,9 +55,8 @@ export class AbstractBar extends Mark {
}
render(I, scales, channels, dimensions) {
const {rx, ry} = this;
const {z: Z, title: L, fill: F, fillOpacity: FO, stroke: S, strokeOpacity: SO} = channels;
const {title: L, fill: F, fillOpacity: FO, stroke: S, strokeOpacity: SO} = channels;
const index = filter(I, ...this._positions(channels), F, FO, S, SO);
if (Z) index.sort((i, j) => ascending(Z[i], Z[j]));
return create("svg:g")
.call(applyIndirectStyles, this)
.call(this._transform, scales)
Expand Down
6 changes: 1 addition & 5 deletions src/marks/dot.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import {ascending} from "d3";
import {create} from "d3";
import {filter, positive} from "../defined.js";
import {Mark, identity, maybeColor, maybeNumber, maybeTuple, title} from "../mark.js";
Expand All @@ -10,7 +9,6 @@ export class Dot extends Mark {
{
x,
y,
z,
r,
title,
fill,
Expand All @@ -30,7 +28,6 @@ export class Dot extends Mark {
[
{name: "x", value: x, scale: "x", optional: true},
{name: "y", value: y, scale: "y", optional: true},
{name: "z", value: z, optional: true},
{name: "r", value: vr, scale: "r", optional: true},
{name: "title", value: title, optional: true},
{name: "fill", value: vfill, scale: "color", optional: true},
Expand All @@ -53,12 +50,11 @@ export class Dot extends Mark {
render(
I,
{x, y},
{x: X, y: Y, z: Z, r: R, title: L, fill: F, fillOpacity: FO, stroke: S, strokeOpacity: SO},
{x: X, y: Y, r: R, title: L, fill: F, fillOpacity: FO, stroke: S, strokeOpacity: SO},
{width, height, marginTop, marginRight, marginBottom, marginLeft}
) {
let index = filter(I, X, Y, F, FO, S, SO);
if (R) index = index.filter(i => positive(R[i]));
if (Z) index.sort((i, j) => ascending(Z[i], Z[j]));
return create("svg:g")
.call(applyIndirectStyles, this)
.call(applyTransform, x, y, 0.5, 0.5)
Expand Down
6 changes: 1 addition & 5 deletions src/marks/link.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import {ascending} from "d3";
import {create} from "d3";
import {filter} from "../defined.js";
import {Mark, maybeColor, maybeNumber, title} from "../mark.js";
Expand All @@ -12,7 +11,6 @@ export class Link extends Mark {
y1,
x2,
y2,
z,
title,
stroke,
strokeOpacity,
Expand All @@ -28,7 +26,6 @@ export class Link extends Mark {
{name: "y1", value: y1, scale: "y"},
{name: "x2", value: x2, scale: "x"},
{name: "y2", value: y2, scale: "y"},
{name: "z", value: z, optional: true},
{name: "title", value: title, optional: true},
{name: "stroke", value: vstroke, scale: "color", optional: true},
{name: "strokeOpacity", value: vstrokeOpacity, scale: "opacity", optional: true}
Expand All @@ -44,10 +41,9 @@ export class Link extends Mark {
render(
I,
{x, y},
{x1: X1, y1: Y1, x2: X2, y2: Y2, z: Z, title: L, stroke: S, strokeOpacity: SO}
{x1: X1, y1: Y1, x2: X2, y2: Y2, title: L, stroke: S, strokeOpacity: SO}
) {
const index = filter(I, X1, Y1, X2, Y2, S, SO);
if (Z) index.sort((i, j) => ascending(Z[i], Z[j]));
return create("svg:g")
.call(applyIndirectStyles, this)
.call(applyTransform, x, y, 0.5, 0.5)
Expand Down
6 changes: 1 addition & 5 deletions src/marks/rect.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import {ascending} from "d3";
import {create} from "d3";
import {filter} from "../defined.js";
import {Mark, number, maybeColor, maybeZero, title, maybeNumber} from "../mark.js";
Expand All @@ -12,7 +11,6 @@ export class Rect extends Mark {
y1,
x2,
y2,
z,
title,
fill,
fillOpacity,
Expand All @@ -39,7 +37,6 @@ export class Rect extends Mark {
{name: "y1", value: y1, scale: "y"},
{name: "x2", value: x2, scale: "x"},
{name: "y2", value: y2, scale: "y"},
{name: "z", value: z, optional: true},
{name: "title", value: title, optional: true},
{name: "fill", value: vfill, scale: "color", optional: true},
{name: "fillOpacity", value: vfillOpacity, scale: "opacity", optional: true},
Expand All @@ -65,11 +62,10 @@ export class Rect extends Mark {
render(
I,
{x, y},
{x1: X1, y1: Y1, x2: X2, y2: Y2, z: Z, title: L, fill: F, fillOpacity: FO, stroke: S, strokeOpacity: SO}
{x1: X1, y1: Y1, x2: X2, y2: Y2, title: L, fill: F, fillOpacity: FO, stroke: S, strokeOpacity: SO}
) {
const {rx, ry} = this;
const index = filter(I, X1, Y2, X2, Y2, F, FO, S, SO);
if (Z) index.sort((i, j) => ascending(Z[i], Z[j]));
return create("svg:g")
.call(applyIndirectStyles, this)
.call(applyTransform, x, y)
Expand Down
11 changes: 2 additions & 9 deletions src/marks/rule.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import {ascending} from "d3";
import {create} from "d3";
import {filter} from "../defined.js";
import {Mark, identity, maybeColor, zero, title, number} from "../mark.js";
Expand All @@ -11,7 +10,6 @@ export class RuleX extends Mark {
x,
y1,
y2,
z,
title,
stroke,
inset = 0,
Expand All @@ -27,7 +25,6 @@ export class RuleX extends Mark {
{name: "x", value: x, scale: "x", optional: true},
{name: "y1", value: y1, scale: "y", optional: true},
{name: "y2", value: y2, scale: "y", optional: true},
{name: "z", value: z, optional: true},
{name: "title", value: title, optional: true},
{name: "stroke", value: vstroke, scale: "color", optional: true}
],
Expand All @@ -40,11 +37,10 @@ export class RuleX extends Mark {
render(
I,
{x, y},
{x: X, y1: Y1, y2: Y2, z: Z, title: L, stroke: S},
{x: X, y1: Y1, y2: Y2, title: L, stroke: S},
{width, height, marginTop, marginRight, marginLeft, marginBottom}
) {
const index = filter(I, X, Y1, Y2, S);
if (Z) index.sort((i, j) => ascending(Z[i], Z[j]));
return create("svg:g")
.call(applyIndirectStyles, this)
.call(applyTransform, X && x, null, 0.5, 0)
Expand All @@ -69,7 +65,6 @@ export class RuleY extends Mark {
x1,
x2,
y,
z,
title,
stroke,
inset = 0,
Expand All @@ -85,7 +80,6 @@ export class RuleY extends Mark {
{name: "y", value: y, scale: "y", optional: true},
{name: "x1", value: x1, scale: "x", optional: true},
{name: "x2", value: x2, scale: "x", optional: true},
{name: "z", value: z, optional: true},
{name: "title", value: title, optional: true},
{name: "stroke", value: vstroke, scale: "color", optional: true}
],
Expand All @@ -98,11 +92,10 @@ export class RuleY extends Mark {
render(
I,
{x, y},
{y: Y, x1: X1, x2: X2, z: Z, title: L, stroke: S},
{y: Y, x1: X1, x2: X2, title: L, stroke: S},
{width, height, marginTop, marginRight, marginLeft, marginBottom}
) {
const index = filter(I, Y, X1, X2);
if (Z) index.sort((i, j) => ascending(Z[i], Z[j]));
return create("svg:g")
.call(applyIndirectStyles, this)
.call(applyTransform, null, Y && y, 0, 0.5)
Expand Down
6 changes: 1 addition & 5 deletions src/marks/text.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import {ascending} from "d3";
import {create} from "d3";
import {filter, nonempty} from "../defined.js";
import {Mark, indexOf, identity, string, title, maybeColor, maybeNumber, maybeTuple, numberChannel} from "../mark.js";
Expand All @@ -10,7 +9,6 @@ export class Text extends Mark {
{
x,
y,
z,
text = indexOf,
title,
fill,
Expand All @@ -36,7 +34,6 @@ export class Text extends Mark {
[
{name: "x", value: x, scale: "x", optional: true},
{name: "y", value: y, scale: "y", optional: true},
{name: "z", value: z, optional: true},
{name: "fontSize", value: numberChannel(vfontSize), optional: true},
{name: "rotate", value: numberChannel(vrotate), optional: true},
{name: "text", value: text},
Expand All @@ -60,12 +57,11 @@ export class Text extends Mark {
render(
I,
{x, y},
{x: X, y: Y, z: Z, rotate: R, text: T, title: L, fill: F, fillOpacity: FO, fontSize: FS},
{x: X, y: Y, rotate: R, text: T, title: L, fill: F, fillOpacity: FO, fontSize: FS},
{width, height, marginTop, marginRight, marginBottom, marginLeft}
) {
const {rotate} = this;
const index = filter(I, X, Y, F, FO, R).filter(i => nonempty(T[i]));
if (Z) index.sort((i, j) => ascending(Z[i], Z[j]));
const cx = (marginLeft + width - marginRight) / 2;
const cy = (marginTop + height - marginBottom) / 2;
return create("svg:g")
Expand Down
6 changes: 1 addition & 5 deletions src/marks/tick.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,3 @@
import {ascending} from "d3";
import {create} from "d3";
import {filter} from "../defined.js";
import {Mark, identity, maybeColor, title} from "../mark.js";
Expand All @@ -9,7 +8,6 @@ class AbstractTick extends Mark {
data,
channels,
{
z,
title,
stroke,
...options
Expand All @@ -20,7 +18,6 @@ class AbstractTick extends Mark {
data,
[
...channels,
{name: "z", value: z, optional: true},
{name: "title", value: title, optional: true},
{name: "stroke", value: vstroke, scale: "color", optional: true}
],
Expand All @@ -29,9 +26,8 @@ class AbstractTick extends Mark {
Style(this, {stroke: cstroke, ...options});
}
render(I, scales, channels, dimensions) {
const {x: X, y: Y, z: Z, title: L, stroke: S} = channels;
const {x: X, y: Y, title: L, stroke: S} = channels;
const index = filter(I, X, Y, S);
if (Z) index.sort((i, j) => ascending(Z[i], Z[j]));
return create("svg:g")
.call(applyIndirectStyles, this)
.call(this._transform, scales)
Expand Down
13 changes: 6 additions & 7 deletions src/transforms/bin.js
Original file line number Diff line number Diff line change
Expand Up @@ -69,12 +69,7 @@ function binn(
z: GZ,
fill: GF,
stroke: GS,
...options,
...BX1 ? {x1: BX1, x2: BX2, x: mid(BX1, BX2)} : {x},
...BY1 ? {y1: BY1, y2: BY2, y: mid(BY1, BY2)} : {y},
...GK && {[gk]: GK},
...Object.fromEntries(outputs.map(({name, output}) => [name, output])),
transform: maybeTransform(options, (data, facets) => {
...maybeTransform(options, (data, facets) => {
const K = valueof(data, k);
const Z = valueof(data, z);
const F = valueof(data, vfill);
Expand Down Expand Up @@ -121,7 +116,11 @@ function binn(
groupFacets.push(groupFacet);
}
return {data: groupData, facets: groupFacets};
})
}),
...BX1 ? {x1: BX1, x2: BX2, x: mid(BX1, BX2)} : {x},
...BY1 ? {y1: BY1, y2: BY2, y: mid(BY1, BY2)} : {y},
...GK && {[gk]: GK},
...Object.fromEntries(outputs.map(({name, output}) => [name, output]))
};
}

Expand Down
11 changes: 5 additions & 6 deletions src/transforms/group.js
Original file line number Diff line number Diff line change
Expand Up @@ -57,11 +57,7 @@ function groupn(
z: GZ,
fill: GF,
stroke: GS,
...options,
...GX && {x: GX},
...GY && {y: GY},
...Object.fromEntries(outputs.map(({name, output}) => [name, output])),
transform: maybeTransform(options, (data, facets) => {
...maybeTransform(options, (data, facets) => {
const X = valueof(data, x);
const Y = valueof(data, y);
const Z = valueof(data, z);
Expand Down Expand Up @@ -97,7 +93,10 @@ function groupn(
groupFacets.push(groupFacet);
}
return {data: groupData, facets: groupFacets};
})
}),
...GX && {x: GX},
...GY && {y: GY},
...Object.fromEntries(outputs.map(({name, output}) => [name, output]))
};
}

Expand Down
7 changes: 3 additions & 4 deletions src/transforms/map.js
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,7 @@ export function map(outputs = {}, options = {}) {
return {key, input, output, setOutput, map: maybeMap(map)};
});
return {
...options,
...Object.fromEntries(channels.map(({key, output}) => [key, output])),
transform: maybeTransform(options, (data, facets) => {
...maybeTransform(options, (data, facets) => {
const Z = valueof(data, z);
const X = channels.map(({input}) => valueof(data, input));
const MX = channels.map(({setOutput}) => setOutput(new Array(data.length)));
Expand All @@ -34,7 +32,8 @@ export function map(outputs = {}, options = {}) {
}
}
return {data, facets};
})
}),
...Object.fromEntries(channels.map(({key, output}) => [key, output]))
};
}

Expand Down
Loading

0 comments on commit 559dd81

Please sign in to comment.