{
const width = 928;
const height = 500;
const marginLeft = 40;
const marginTop = 40;
const marginRight = 40;
const marginBottom = 40;
const w = width - marginLeft - marginRight;
const h = height - marginTop - marginBottom;
const wrapper = d3.create("div");
const canvas = wrapper.append("canvas")
.attr("width", w)
.attr("height", 1)
.attr("style", `width:${w}px;height:80px;margin:20px 40px;background:#ccc;`);
const context = canvas.node().getContext("2d");
const svg = wrapper.append("svg").attr("width", width).attr("height", height);
const x0 = d3.scaleQuantize()
.domain([0, 1])
.range(["#8e0152", "#c51b7d", "#de77ae", "#f1b6da", "#fde0ef", "#f7f7f7", "#e6f5d0", "#b8e186", "#7fbc41", "#4d9221", "#276419"]);
const x1 = d3.scalePoint(x0.range(), [0, w]);
const x2 = d3.scaleLinear([0, 1], [0, w]);
const y = d3.scaleLinear([0, 255], [h, 0]);
const g = svg.append("g")
.attr("transform", `translate(${marginLeft},${marginTop})`);
g.append("g")
.selectAll("circle")
.data(x1.domain())
.enter().append("circle")
.attr("cx", x1)
.attr("r", 20)
.attr("fill", d => d);
g.append("g")
.attr("class", "axis axis--x")
.call(d3.axisTop(x1).tickPadding(18));
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y));
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x2));
const line = g.append("g")
.attr("class", "lines")
.selectAll("path")
.data(["r", "g", "b"].map(function(channel) {
const colors = x0.range().map(function(c) { return d3.rgb(c); }), n = colors.length;
return colors.map((c, i) => [i / (n - 1), c[channel]]);
}))
.enter().append("g")
.attr("fill", "none")
.attr("stroke", (d, i) => ["#f00", "#0f0", "#00f"][i]);
line.append("path")
.attr("stroke-width", 3)
.attr("d", (values) => {
const i = d3.interpolateBasis(values.map((v) => v[1]));
return d3.line()
.x(x2)
.y((t) => y(i(t)))
(d3.ticks(0, 1, 200));
});
line.append("path")
.attr("stroke-dasharray", "2,2")
.attr("stroke", "#000")
.attr("d", d3.line()
.curve(d3.curveLinear)
.x((d) => x2(d[0]))
.y((d) => y(d[1])));
const image = context.createImageData(w, 1);
const interpolate = d3.interpolateRgbBasis(x0.range());
for (let i = 0, k = 0; i < w; ++i, k += 4) {
const c = d3.rgb(interpolate(i / (w - 1)));
image.data[k] = c.r;
image.data[k + 1] = c.g;
image.data[k + 2] = c.b;
image.data[k + 3] = 255;
}
context.putImageData(image, 0, 0);
return wrapper.node();
}