Skip to content

Commit d5359e8

Browse files
committed
paint
1 parent 7b92d54 commit d5359e8

File tree

5 files changed

+40
-13
lines changed

5 files changed

+40
-13
lines changed

src/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,3 +45,4 @@ export {pointer, pointerX, pointerY} from "./interactions/pointer.js";
4545
export {formatIsoDate, formatWeekday, formatMonth} from "./format.js";
4646
export {scale} from "./scales.js";
4747
export {legend} from "./legends.js";
48+
export {linearGradient} from "./paint.js";

src/options.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -442,12 +442,17 @@ export function isEvery(values, is) {
442442
return every;
443443
}
444444

445+
export function isPaint(value) {
446+
return typeof value?.paint === "function";
447+
}
448+
445449
// Mostly relies on d3-color, with a few extra color keywords. Currently this
446450
// strictly requires that the value be a string; we might want to apply string
447451
// coercion here, though note that d3-color instances would need to support
448452
// valueOf to work correctly with InternMap.
449453
// https://www.w3.org/TR/SVG11/painting.html#SpecifyingPaint
450454
export function isColor(value) {
455+
if (isPaint(value)) return true;
451456
if (typeof value !== "string") return false;
452457
value = value.toLowerCase().trim();
453458
return (

src/paint.js

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
import {create} from "./context.js";
2+
3+
export function linearGradient() {
4+
return {
5+
paint(context) {
6+
const gradient = create("svg:linearGradient", context).attr("gradientTransform", "rotate(90)");
7+
gradient.append("stop").attr("offset", "5%").attr("stop-color", "purple");
8+
gradient.append("stop").attr("offset", "75%").attr("stop-color", "red");
9+
gradient.append("stop").attr("offset", "100%").attr("stop-color", "gold");
10+
return gradient.node();
11+
}
12+
};
13+
}

src/style.js

Lines changed: 11 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,17 +2,8 @@ import {geoPath, group, namespaces} from "d3";
22
import {create} from "./context.js";
33
import {defined, nonempty} from "./defined.js";
44
import {formatDefault} from "./format.js";
5-
import {
6-
string,
7-
number,
8-
maybeColorChannel,
9-
maybeNumberChannel,
10-
maybeKeyword,
11-
isNoneish,
12-
isNone,
13-
isRound,
14-
keyof
15-
} from "./options.js";
5+
import {isNone, isNoneish, isPaint, isRound} from "./options.js";
6+
import {keyof, maybeColorChannel, maybeKeyword, maybeNumberChannel, number, string} from "./options.js";
167
import {warn} from "./warnings.js";
178

189
export const offset = (typeof window !== "undefined" ? window.devicePixelRatio > 1 : typeof it === "undefined") ? 0 : 0.5; // prettier-ignore
@@ -115,7 +106,7 @@ export function styles(
115106

116107
// Some marks don’t support fill (e.g., tick and rule).
117108
if (defaultFill !== null) {
118-
mark.fill = impliedString(cfill, "currentColor");
109+
mark.fill = isPaint(cfill) ? cfill : impliedString(cfill, "currentColor");
119110
mark.fillOpacity = impliedNumber(cfillOpacity, 1);
120111
}
121112

@@ -364,7 +355,14 @@ function applyClip(selection, mark, dimensions, context) {
364355
// Note: may mutate selection.node!
365356
export function applyIndirectStyles(selection, mark, dimensions, context) {
366357
applyClip(selection, mark, dimensions, context);
367-
applyAttr(selection, "fill", mark.fill);
358+
if (isPaint(mark.fill)) {
359+
const paint = mark.fill.paint(context);
360+
paint.setAttribute("id", "test-paint");
361+
context.ownerSVGElement.append(paint);
362+
selection.attr("fill", "url(#test-paint)");
363+
} else {
364+
applyAttr(selection, "fill", mark.fill);
365+
}
368366
applyAttr(selection, "fill-opacity", mark.fillOpacity);
369367
applyAttr(selection, "stroke", mark.stroke);
370368
applyAttr(selection, "stroke-width", mark.strokeWidth);

test/plots/penguin-species.ts

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,16 @@ export async function penguinSpeciesCheysson() {
2929
});
3030
}
3131

32+
export async function penguinSpeciesPaint() {
33+
const penguins = await d3.csv<any>("data/penguins.csv", d3.autoType);
34+
return Plot.plot({
35+
marks: [
36+
Plot.barY(penguins, Plot.groupX({y: "count"}, {x: "species", fill: Plot.linearGradient()})),
37+
Plot.ruleY([0])
38+
]
39+
});
40+
}
41+
3242
export async function penguinSpeciesGradient() {
3343
const penguins = await d3.csv<any>("data/penguins.csv", d3.autoType);
3444
return Plot.plot({

0 commit comments

Comments
 (0)