Skip to content

Commit

Permalink
unique clip paths
Browse files Browse the repository at this point in the history
- smaller files
- better interaction performance
  • Loading branch information
Fil committed Aug 22, 2023
1 parent 5625c89 commit 5658113
Show file tree
Hide file tree
Showing 18 changed files with 323 additions and 879 deletions.
65 changes: 38 additions & 27 deletions src/style.js
Original file line number Diff line number Diff line change
@@ -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";
Expand Down Expand Up @@ -306,43 +306,54 @@ export function maybeClip(clip) {
return clip;
}

// TODO avoid creating a new clip-path each time?
function clipDefs({ownerSVGElement}) {
const svg = select(ownerSVGElement);
const defs = svg.select("defs.clip");
return defs.size() ? defs : svg.insert("defs", ":first-child").attr("class", "clip");
}

// Note: may mutate selection.node!
const frame = Symbol("frame");
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!
});
const clips = context.clips ?? (context.clips = new WeakMap());
if (!clips.has(frame)) {
const {width, height, marginLeft, marginRight, marginTop, marginBottom} = dimensions;
const id = getClipId();
clips.set(frame, id);
clipDefs(context)
.append("clipPath")
.attr("id", id)
.append("rect")
.attr("x", marginLeft)
.attr("y", marginTop)
.attr("width", width - marginRight - marginLeft)
.attr("height", height - marginTop - marginBottom);
}
selection = create("svg:g", context).each(function () {
this.appendChild(selection.node());
selection.node = () => this; // Note: mutation!
});
clipUrl = `url(#${clips.get(frame)})`;
break;
}
case "sphere": {
const clips = context.clips ?? (context.clips = new WeakMap());
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"}));
if (!clips.has(projection)) {
const id = getClipId();
clips.set(projection, id);
clipDefs(context)
.append("clipPath")
.attr("id", id)
.append("path")
.attr("d", geoPath(projection)({type: "Sphere"}));
}
clipUrl = `url(#${clips.get(projection)})`;
break;
}
}
Expand Down
13 changes: 6 additions & 7 deletions test/output/armadillo.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 5 additions & 3 deletions test/output/bandClip.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
8 changes: 5 additions & 3 deletions test/output/bandClip2.svg
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Loading

0 comments on commit 5658113

Please sign in to comment.