diff --git a/src/axis.js b/src/axis.js
index 345cd61a27..18f296cab8 100644
--- a/src/axis.js
+++ b/src/axis.js
@@ -1,6 +1,6 @@
import {axisTop, axisBottom, axisRight, axisLeft, create, format, utcFormat} from "d3";
import {formatIsoDate} from "./format.js";
-import {boolean, number, string, keyword, maybeKeyword, constant, isTemporal} from "./mark.js";
+import {boolean, take, number, string, keyword, maybeKeyword, constant, isTemporal} from "./mark.js";
export class AxisX {
constructor({
@@ -67,7 +67,7 @@ export class AxisX {
.attr("font-family", null)
.call(!line ? g => g.select(".domain").remove() : () => {})
.call(!grid ? () => {}
- : fy ? gridFacetX(fy, -ty)
+ : fy ? gridFacetX(index, fy, -ty)
: gridX(offsetSign * (marginBottom + marginTop - height)))
.call(!label ? () => {} : g => g.append("text")
.attr("fill", "currentColor")
@@ -148,7 +148,7 @@ export class AxisY {
.attr("font-family", null)
.call(!line ? g => g.select(".domain").remove() : () => {})
.call(!grid ? () => {}
- : fx ? gridFacetY(fx, -tx)
+ : fx ? gridFacetY(index, fx, -tx)
: gridY(offsetSign * (marginLeft + marginRight - width)))
.call(!label ? () => {} : g => g.append("text")
.attr("fill", "currentColor")
@@ -182,22 +182,24 @@ function gridY(x2) {
.attr("x2", x2);
}
-function gridFacetX(fy, ty) {
+function gridFacetX(index, fy, ty) {
const dy = fy.bandwidth();
+ const domain = fy.domain();
return g => g.selectAll(".tick")
.append("path")
.attr("stroke", "currentColor")
.attr("stroke-opacity", 0.1)
- .attr("d", fy.domain().map(v => `M0,${fy(v) + ty}v${dy}`).join(""));
+ .attr("d", (index ? take(domain, index) : domain).map(v => `M0,${fy(v) + ty}v${dy}`).join(""));
}
-function gridFacetY(fx, tx) {
+function gridFacetY(index, fx, tx) {
const dx = fx.bandwidth();
+ const domain = fx.domain();
return g => g.selectAll(".tick")
.append("path")
.attr("stroke", "currentColor")
.attr("stroke-opacity", 0.1)
- .attr("d", fx.domain().map(v => `M${fx(v) + tx},0h${dx}`).join(""));
+ .attr("d", (index ? take(domain, index) : domain).map(v => `M${fx(v) + tx},0h${dx}`).join(""));
}
function createAxis(axis, scale, {ticks, tickSize, tickPadding, tickFormat}) {
diff --git a/src/facet.js b/src/facet.js
index f42d944530..62b198f2b4 100644
--- a/src/facet.js
+++ b/src/facet.js
@@ -1,6 +1,6 @@
import {cross, difference, groups, InternMap} from "d3";
import {create} from "d3";
-import {Mark, first, second, markify} from "./mark.js";
+import {Mark, first, second, markify, where} from "./mark.js";
import {applyScales} from "./scales.js";
import {filterStyles} from "./style.js";
@@ -24,7 +24,6 @@ class Facet extends Mark {
this.marks = marks.flat(Infinity).map(markify);
// The following fields are set by initialize:
this.marksChannels = undefined; // array of mark channels
- this.marksIndex = undefined; // array of mark indexes (for non-faceted marks)
this.marksIndexByFacet = undefined; // map from facet key to array of mark indexes
}
initialize() {
@@ -34,7 +33,6 @@ class Facet extends Mark {
const facetsIndex = Array.from(facets, second);
const subchannels = [];
const marksChannels = this.marksChannels = [];
- const marksIndex = this.marksIndex = new Array(this.marks.length);
const marksIndexByFacet = this.marksIndexByFacet = facetMap(channels);
for (const facetKey of facetsKeys) {
marksIndexByFacet.set(facetKey, new Array(this.marks.length));
@@ -57,12 +55,10 @@ class Facet extends Mark {
for (let j = 0; j < facetsKeys.length; ++j) {
marksIndexByFacet.get(facetsKeys[j])[i] = I[j];
}
- marksIndex[i] = []; // implicit empty index for sparse facets
} else {
for (let j = 0; j < facetsKeys.length; ++j) {
marksIndexByFacet.get(facetsKeys[j])[i] = I;
}
- marksIndex[i] = I;
}
}
for (const [, channel] of markChannels) {
@@ -73,8 +69,10 @@ class Facet extends Mark {
return {index, channels: [...channels, ...subchannels]};
}
render(I, scales, channels, dimensions, axes) {
- const {marks, marksChannels, marksIndex, marksIndexByFacet} = this;
+ const {marks, marksChannels, marksIndexByFacet} = this;
const {fx, fy} = scales;
+ const fyDomain = fy && fy.domain();
+ const fxDomain = fx && fx.domain();
const fyMargins = fy && {marginTop: 0, marginBottom: 0, height: fy.bandwidth()};
const fxMargins = fx && {marginRight: 0, marginLeft: 0, width: fx.bandwidth()};
const subdimensions = {...dimensions, ...fxMargins, ...fyMargins};
@@ -82,35 +80,43 @@ class Facet extends Mark {
return create("svg:g")
.call(g => {
if (fy && axes.y) {
- const domain = fy.domain();
const axis1 = axes.y, axis2 = nolabel(axis1);
- const j = axis1.labelAnchor === "bottom" ? domain.length - 1 : axis1.labelAnchor === "center" ? domain.length >> 1 : 0;
+ const j = axis1.labelAnchor === "bottom" ? fyDomain.length - 1 : axis1.labelAnchor === "center" ? fyDomain.length >> 1 : 0;
const fyDimensions = {...dimensions, ...fyMargins};
g.selectAll()
- .data(domain)
+ .data(fyDomain)
.join("g")
.attr("transform", ky => `translate(0,${fy(ky)})`)
- .append((_, i) => (i === j ? axis1 : axis2).render(null, scales, null, fyDimensions));
+ .append((ky, i) => (i === j ? axis1 : axis2).render(
+ fx && where(fxDomain, kx => marksIndexByFacet.has([kx, ky])),
+ scales,
+ null,
+ fyDimensions
+ ));
}
if (fx && axes.x) {
- const domain = fx.domain();
const axis1 = axes.x, axis2 = nolabel(axis1);
- const j = axis1.labelAnchor === "right" ? domain.length - 1 : axis1.labelAnchor === "center" ? domain.length >> 1 : 0;
+ const j = axis1.labelAnchor === "right" ? fxDomain.length - 1 : axis1.labelAnchor === "center" ? fxDomain.length >> 1 : 0;
const {marginLeft, marginRight} = dimensions;
const fxDimensions = {...dimensions, ...fxMargins, labelMarginLeft: marginLeft, labelMarginRight: marginRight};
g.selectAll()
- .data(domain)
+ .data(fxDomain)
.join("g")
.attr("transform", kx => `translate(${fx(kx)},0)`)
- .append((_, i) => (i === j ? axis1 : axis2).render(null, scales, null, fxDimensions));
+ .append((kx, i) => (i === j ? axis1 : axis2).render(
+ fy && where(fyDomain, ky => marksIndexByFacet.has([kx, ky])),
+ scales,
+ null,
+ fxDimensions
+ ));
}
})
.call(g => g.selectAll()
- .data(facetKeys(scales))
+ .data(facetKeys(scales).filter(marksIndexByFacet.has, marksIndexByFacet))
.join("g")
.attr("transform", facetTranslate(fx, fy))
.each(function(key) {
- const marksFacetIndex = marksIndexByFacet.get(key) || marksIndex;
+ const marksFacetIndex = marksIndexByFacet.get(key);
for (let i = 0; i < marks.length; ++i) {
const values = marksValues[i];
const index = filterStyles(marksFacetIndex[i], values);
diff --git a/src/mark.js b/src/mark.js
index 1b670dad6e..19e5706793 100644
--- a/src/mark.js
+++ b/src/mark.js
@@ -230,6 +230,11 @@ export function range(data) {
return Uint32Array.from(data, indexOf);
}
+// Returns a filtered range of data given the test function.
+export function where(data, test) {
+ return range(data).filter(i => test(data[i], i, data));
+}
+
// Returns an array [values[index[0]], values[index[1]], …].
export function take(values, index) {
return Array.from(index, i => values[i]);
diff --git a/test/output/penguinCulmen.svg b/test/output/penguinCulmen.svg
index d98f6a61e4..b579f95286 100644
--- a/test/output/penguinCulmen.svg
+++ b/test/output/penguinCulmen.svg
@@ -50,23 +50,23 @@
35
-
+
40
-
+
45
-
+
50
-
+
55
-
+
@@ -122,11 +122,11 @@
15
-
+
20
-
+
culmen_depth_mm →
@@ -2573,11 +2573,6 @@
-
-
-
-
-
diff --git a/test/output/penguinCulmenArray.svg b/test/output/penguinCulmenArray.svg
index 9f89051fc0..4519fca6ce 100644
--- a/test/output/penguinCulmenArray.svg
+++ b/test/output/penguinCulmenArray.svg
@@ -50,23 +50,23 @@
35
-
+
40
-
+
45
-
+
50
-
+
55
-
+
@@ -122,11 +122,11 @@
15
-
+
20
-
+
@@ -2904,353 +2904,6 @@
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
diff --git a/test/output/penguinMassSexSpecies.svg b/test/output/penguinMassSexSpecies.svg
index 3eb26dd0d2..984e5f4ab2 100644
--- a/test/output/penguinMassSexSpecies.svg
+++ b/test/output/penguinMassSexSpecies.svg
@@ -185,12 +185,6 @@
-
-
-
-
-
-