diff --git a/src/style.js b/src/style.js index f984750bf4..94e4742ee0 100644 --- a/src/style.js +++ b/src/style.js @@ -1,4 +1,4 @@ -import {geoPath, group, namespaces} from "d3"; +import {geoPath, group, namespaces, select} from "d3"; import {create} from "./context.js"; import {defined, nonempty} from "./defined.js"; import {formatDefault} from "./format.js"; @@ -302,43 +302,25 @@ export function* groupIndex(I, position, mark, channels) { } } -// TODO avoid creating a new clip-path each time? // Note: may mutate selection.node! function applyClip(selection, mark, dimensions, context) { let clipUrl; const {clip = context.clip} = mark; switch (clip) { case "frame": { - const {width, height, marginLeft, marginRight, marginTop, marginBottom} = dimensions; - const id = getClipId(); - clipUrl = `url(#${id})`; - selection = create("svg:g", context) - .call((g) => - g - .append("svg:clipPath") - .attr("id", id) - .append("rect") - .attr("x", marginLeft) - .attr("y", marginTop) - .attr("width", width - marginRight - marginLeft) - .attr("height", height - marginTop - marginBottom) - ) - .each(function () { - this.appendChild(selection.node()); - selection.node = () => this; // Note: mutation! - }); + // Wrap the G element with another (untransformed) G element, applying the + // clip to the parent G element so that the clip path is not affected by + // the mark’s transform. To simplify the adoption of this fix, mutate the + // passed-in selection.node to return the parent G element. + selection = create("svg:g", context).each(function () { + this.appendChild(selection.node()); + selection.node = () => this; // Note: mutation! + }); + clipUrl = getFrameClip(context, dimensions); break; } case "sphere": { - const {projection} = context; - if (!projection) throw new Error(`the "sphere" clip option requires a projection`); - const id = getClipId(); - clipUrl = `url(#${id})`; - selection - .append("clipPath") - .attr("id", id) - .append("path") - .attr("d", geoPath(projection)({type: "Sphere"})); + clipUrl = getProjectionClip(context); break; } } @@ -351,6 +333,35 @@ function applyClip(selection, mark, dimensions, context) { applyAttr(selection, "clip-path", clipUrl); } +function memoizeClip(clip) { + const cache = new WeakMap(); + return (context, dimensions) => { + let url = cache.get(context); + if (!url) { + const id = getClipId(); + select(context.ownerSVGElement).append("clipPath").attr("id", id).call(clip, context, dimensions); + cache.set(context, (url = `url(#${id})`)); + } + return url; + }; +} + +const getFrameClip = memoizeClip((clipPath, context, dimensions) => { + const {width, height, marginLeft, marginRight, marginTop, marginBottom} = dimensions; + clipPath + .append("rect") + .attr("x", marginLeft) + .attr("y", marginTop) + .attr("width", width - marginRight - marginLeft) + .attr("height", height - marginTop - marginBottom); +}); + +const getProjectionClip = memoizeClip((clipPath, context) => { + const {projection} = context; + if (!projection) throw new Error(`the "sphere" clip option requires a projection`); + clipPath.append("path").attr("d", geoPath(projection)({type: "Sphere"})); +}); + // Note: may mutate selection.node! export function applyIndirectStyles(selection, mark, dimensions, context) { applyClip(selection, mark, dimensions, context); diff --git a/test/output/aaplBollingerCandlestick.svg b/test/output/aaplBollingerCandlestick.svg index 1115051552..b8a7f75915 100644 --- a/test/output/aaplBollingerCandlestick.svg +++ b/test/output/aaplBollingerCandlestick.svg @@ -74,18 +74,15 @@ May Jun + + + - - - - - - - + @@ -1349,10 +1346,7 @@ - - - - + diff --git a/test/output/aaplCloseClip.svg b/test/output/aaplCloseClip.svg index 8e4130019d..61820798db 100644 --- a/test/output/aaplCloseClip.svg +++ b/test/output/aaplCloseClip.svg @@ -82,18 +82,15 @@ 22 29 + + + - - - - - - - + diff --git a/test/output/armadillo.svg b/test/output/armadillo.svg index 035971352f..4c9e4ee088 100644 --- a/test/output/armadillo.svg +++ b/test/output/armadillo.svg @@ -13,16 +13,13 @@ white-space: pre; } + + + - - - - - - - + diff --git a/test/output/bandClip.svg b/test/output/bandClip.svg index 53a7ae4069..8d481ce295 100644 --- a/test/output/bandClip.svg +++ b/test/output/bandClip.svg @@ -34,10 +34,10 @@ C + + + - - - A B diff --git a/test/output/bandClip2.svg b/test/output/bandClip2.svg index a72fafc75e..06d376c3bc 100644 --- a/test/output/bandClip2.svg +++ b/test/output/bandClip2.svg @@ -82,10 +82,10 @@ + + + - - - diff --git a/test/output/contourVapor.svg b/test/output/contourVapor.svg index 338dbdd68d..34f7b908d2 100644 --- a/test/output/contourVapor.svg +++ b/test/output/contourVapor.svg @@ -13,10 +13,10 @@ white-space: pre; } + + + - - - diff --git a/test/output/differenceFilterX.svg b/test/output/differenceFilterX.svg index 50b08ac5aa..42528783f9 100644 --- a/test/output/differenceFilterX.svg +++ b/test/output/differenceFilterX.svg @@ -63,10 +63,10 @@ + + + - - - diff --git a/test/output/differenceFilterY1.svg b/test/output/differenceFilterY1.svg index 24212d85e7..d0f047f8e9 100644 --- a/test/output/differenceFilterY1.svg +++ b/test/output/differenceFilterY1.svg @@ -63,10 +63,10 @@ + + + - - - diff --git a/test/output/differenceFilterY2.svg b/test/output/differenceFilterY2.svg index 7b018f1ff5..5fa3d1a60d 100644 --- a/test/output/differenceFilterY2.svg +++ b/test/output/differenceFilterY2.svg @@ -63,10 +63,10 @@ + + + - - - diff --git a/test/output/differenceX.svg b/test/output/differenceX.svg index a6fe21f02c..427afb43dc 100644 --- a/test/output/differenceX.svg +++ b/test/output/differenceX.svg @@ -91,10 +91,10 @@ + + + - - - diff --git a/test/output/differenceY.svg b/test/output/differenceY.svg index 7ae5005cd0..0ae2fbf577 100644 --- a/test/output/differenceY.svg +++ b/test/output/differenceY.svg @@ -66,10 +66,10 @@ + + + - - - diff --git a/test/output/differenceY1.svg b/test/output/differenceY1.svg index f79da91dd6..151c7955ca 100644 --- a/test/output/differenceY1.svg +++ b/test/output/differenceY1.svg @@ -72,10 +72,10 @@ + + + - - - diff --git a/test/output/differenceYClip.svg b/test/output/differenceYClip.svg index f258e6c8ff..2fa0ea6368 100644 --- a/test/output/differenceYClip.svg +++ b/test/output/differenceYClip.svg @@ -54,10 +54,10 @@ 1980 2000 + + + - - - @@ -65,21 +65,15 @@ - - - - + - + - + - - - - + diff --git a/test/output/differenceYClipVariable.svg b/test/output/differenceYClipVariable.svg index 32956f81ec..6e179dcfaa 100644 --- a/test/output/differenceYClipVariable.svg +++ b/test/output/differenceYClipVariable.svg @@ -54,10 +54,10 @@ 2017 2018 + + + - - - @@ -85,21 +85,15 @@ - - - - + - + - + - - - - + diff --git a/test/output/differenceYConstant.svg b/test/output/differenceYConstant.svg index 163b607c61..60b6fa086e 100644 --- a/test/output/differenceYConstant.svg +++ b/test/output/differenceYConstant.svg @@ -74,10 +74,10 @@ + + + - - - diff --git a/test/output/differenceYCurve.svg b/test/output/differenceYCurve.svg index c873427c9b..7140e341e3 100644 --- a/test/output/differenceYCurve.svg +++ b/test/output/differenceYCurve.svg @@ -80,10 +80,10 @@ + + + - - - diff --git a/test/output/differenceYNegative.svg b/test/output/differenceYNegative.svg index 3317d2a59a..8607b76012 100644 --- a/test/output/differenceYNegative.svg +++ b/test/output/differenceYNegative.svg @@ -60,10 +60,10 @@ + + + - - - diff --git a/test/output/differenceYOrdinal.svg b/test/output/differenceYOrdinal.svg index 4e514a601e..a3c8e33098 100644 --- a/test/output/differenceYOrdinal.svg +++ b/test/output/differenceYOrdinal.svg @@ -55,10 +55,10 @@ + + + - - - diff --git a/test/output/differenceYOrdinalFlip.svg b/test/output/differenceYOrdinalFlip.svg index ad221b90c9..369d5d630d 100644 --- a/test/output/differenceYOrdinalFlip.svg +++ b/test/output/differenceYOrdinalFlip.svg @@ -55,10 +55,10 @@ + + + - - - diff --git a/test/output/differenceYRandom.svg b/test/output/differenceYRandom.svg index 600ada5961..b14e35f8f2 100644 --- a/test/output/differenceYRandom.svg +++ b/test/output/differenceYRandom.svg @@ -59,10 +59,10 @@ + + + - - - diff --git a/test/output/differenceYReverse.svg b/test/output/differenceYReverse.svg index 98efbb5721..f21f52f7e0 100644 --- a/test/output/differenceYReverse.svg +++ b/test/output/differenceYReverse.svg @@ -66,10 +66,10 @@ + + + - - - diff --git a/test/output/differenceYVariable.svg b/test/output/differenceYVariable.svg index 319ee6fc64..36c5964185 100644 --- a/test/output/differenceYVariable.svg +++ b/test/output/differenceYVariable.svg @@ -86,10 +86,10 @@ + + + - - - diff --git a/test/output/differenceYZero.svg b/test/output/differenceYZero.svg index afdf98ffc5..14db8a3f92 100644 --- a/test/output/differenceYZero.svg +++ b/test/output/differenceYZero.svg @@ -66,10 +66,10 @@ + + + - - - diff --git a/test/output/hexbin.svg b/test/output/hexbin.svg index 293342cceb..a2a2505ea3 100644 --- a/test/output/hexbin.svg +++ b/test/output/hexbin.svg @@ -69,10 +69,10 @@ culmen_depth_mm → + + + - - - diff --git a/test/output/hexbinFillX.svg b/test/output/hexbinFillX.svg index bfb1a75523..fd80f6f95d 100644 --- a/test/output/hexbinFillX.svg +++ b/test/output/hexbinFillX.svg @@ -69,10 +69,10 @@ culmen_depth_mm → + + + - - - diff --git a/test/output/hexbinIdentityReduce.svg b/test/output/hexbinIdentityReduce.svg index 9ce724ec63..df736b9267 100644 --- a/test/output/hexbinIdentityReduce.svg +++ b/test/output/hexbinIdentityReduce.svg @@ -73,10 +73,10 @@ culmen_length_mm → + + + - - - diff --git a/test/output/hexbinR.html b/test/output/hexbinR.html index a4f8fd0414..5ade25928a 100644 --- a/test/output/hexbinR.html +++ b/test/output/hexbinR.html @@ -127,27 +127,21 @@ + + + - - - - - - - + - - - - + diff --git a/test/output/hexbinText.svg b/test/output/hexbinText.svg index 2cd15de0a3..e91aee982e 100644 --- a/test/output/hexbinText.svg +++ b/test/output/hexbinText.svg @@ -93,27 +93,21 @@ + + + - - - - - - - + - - - - + diff --git a/test/output/hexbinZ.html b/test/output/hexbinZ.html index 9833c76a21..747c7a9d86 100644 --- a/test/output/hexbinZ.html +++ b/test/output/hexbinZ.html @@ -84,10 +84,10 @@ culmen_length_mm → + + + - - - diff --git a/test/output/hexbinZNull.svg b/test/output/hexbinZNull.svg index aacf31426f..1ad7df392c 100644 --- a/test/output/hexbinZNull.svg +++ b/test/output/hexbinZNull.svg @@ -69,10 +69,10 @@ culmen_depth_mm → + + + - - - diff --git a/test/output/penguinDensityFill.html b/test/output/penguinDensityFill.html index 584f9a2c49..95b5d98908 100644 --- a/test/output/penguinDensityFill.html +++ b/test/output/penguinDensityFill.html @@ -119,11 +119,11 @@ flipper_length_mm → + + + - - - @@ -136,10 +136,7 @@ - - - - + @@ -152,10 +149,7 @@ - - - - + diff --git a/test/output/penguinDensityZ.html b/test/output/penguinDensityZ.html index bebdd3b075..14edf652dc 100644 --- a/test/output/penguinDensityZ.html +++ b/test/output/penguinDensityZ.html @@ -118,11 +118,11 @@ flipper_length_mm → + + + - - - Adelie Adelie @@ -144,10 +144,7 @@ Gentoo - - - - + Adelie Adelie @@ -169,10 +166,7 @@ Chinstrap - - - - + Adelie Adelie diff --git a/test/output/projectionClipBerghaus.svg b/test/output/projectionClipBerghaus.svg index 98cba53328..426da50ca4 100644 --- a/test/output/projectionClipBerghaus.svg +++ b/test/output/projectionClipBerghaus.svg @@ -13,16 +13,13 @@ white-space: pre; } + + + - - - - - - - + diff --git a/test/output/rasterVaporEqualEarth.svg b/test/output/rasterVaporEqualEarth.svg index 0361454e91..fad8839548 100644 --- a/test/output/rasterVaporEqualEarth.svg +++ b/test/output/rasterVaporEqualEarth.svg @@ -13,10 +13,10 @@ white-space: pre; } + + + - - - diff --git a/test/output/rasterVaporEqualEarthBarycentric.svg b/test/output/rasterVaporEqualEarthBarycentric.svg index 71241174cd..a5ba2acced 100644 --- a/test/output/rasterVaporEqualEarthBarycentric.svg +++ b/test/output/rasterVaporEqualEarthBarycentric.svg @@ -13,10 +13,10 @@ white-space: pre; } + + + - - - diff --git a/test/output/roundedRectNegativeX.html b/test/output/roundedRectNegativeX.html index 04bfce0cab..c254ffa29c 100644 --- a/test/output/roundedRectNegativeX.html +++ b/test/output/roundedRectNegativeX.html @@ -102,10 +102,10 @@ Frequency → + + + - - - diff --git a/test/output/roundedRectNegativeY.html b/test/output/roundedRectNegativeY.html index bacbed2611..26a42c24c7 100644 --- a/test/output/roundedRectNegativeY.html +++ b/test/output/roundedRectNegativeY.html @@ -98,10 +98,10 @@ weight → + + + - - - diff --git a/test/output/roundedRectNegativeY1.html b/test/output/roundedRectNegativeY1.html index 3962f3291c..5f78ede10c 100644 --- a/test/output/roundedRectNegativeY1.html +++ b/test/output/roundedRectNegativeY1.html @@ -98,10 +98,10 @@ weight → + + + - - - diff --git a/test/output/trafficHorizon.html b/test/output/trafficHorizon.html index 16feeac2f5..6a17ffe575 100644 --- a/test/output/trafficHorizon.html +++ b/test/output/trafficHorizon.html @@ -50,1531 +50,964 @@ white-space: pre; } + + + - - - - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + - - - - + diff --git a/test/output/usStateCapitalsVoronoi.svg b/test/output/usStateCapitalsVoronoi.svg index c34eef764b..3b77b8a4ec 100644 --- a/test/output/usStateCapitalsVoronoi.svg +++ b/test/output/usStateCapitalsVoronoi.svg @@ -66,17 +66,16 @@ + + + - - - - - - - - + + + + diff --git a/test/output/usStateCentroidVoronoi.svg b/test/output/usStateCentroidVoronoi.svg index cc0ca4df88..9d4b20f061 100644 --- a/test/output/usStateCentroidVoronoi.svg +++ b/test/output/usStateCentroidVoronoi.svg @@ -67,17 +67,16 @@ + + + - - - - - - - - + + + + diff --git a/test/output/usStateGeoCentroidVoronoi.svg b/test/output/usStateGeoCentroidVoronoi.svg index 2ad229543d..ef0a73c090 100644 --- a/test/output/usStateGeoCentroidVoronoi.svg +++ b/test/output/usStateGeoCentroidVoronoi.svg @@ -67,17 +67,16 @@ + + + - - - - - - - - + + + + diff --git a/test/output/youngAdults.html b/test/output/youngAdults.html index f15b78b8a6..630224b643 100644 --- a/test/output/youngAdults.html +++ b/test/output/youngAdults.html @@ -386,51 +386,39 @@

…by age and sex. Data: Eurostat

+ + + - - - - - - - + - - - - + - - - - + - - - - +