Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function slopeChart(multipleData, index) {
const chartSpace = d3.select(this);

const n = multipleData.visits.length;

const x = d3.scalePoint()
.domain(d3.range(n))
.range([params.multiples.margin, params.multiples.width - params.multiples.margin]);
const y = d3.scaleLinear()
.domain(sharedYExtent)
.range([params.multiples.height - params.multiples.margin, params.multiples.margin]);

const line = d3.line()
.x((d, i) => x(i))
.y(y);
const plots = chartSpace.append('g')
.selectAll('g')
.data([multipleData])
.join('g')

plots
.append("g")
.attr("class", "axis axis--left")
.attr("transform", `translate(${params.multiples.margin}, ${0})`)
.call(d3.axisLeft(y)
.tickSizeOuter(0).tickSizeInner(0)
)
.call(g => g.selectAll(".tick").remove())
.call(g => g.selectAll("path.domain").attr("stroke", "#DFDFDF"));
plots
.append("g")
.attr("class", "axis axis--right")
.attr("transform", `translate(${params.multiples.width - params.multiples.margin}, ${0})`)
.call(d3.axisRight(y)
.tickSizeOuter(0).tickSizeInner(0)
)
.call(g => g.selectAll(".tick").remove())
.call(g => g.selectAll("path.domain").attr("stroke", "#DFDFDF"));
plots.append("g")
.attr("class", "context-slopes")
.selectAll("path")
.data(data)
.join("path")
.attr("class", "slope")
.attr("d", d => line(d.visits))
.attr("fill", "none")
.attr("fill-opacity", 0.5)
.attr("stroke-linecap", "butt")
.attr("stroke", "#DFDFDF")
.attr("stroke-width", 0.5);
plots.append('path')
.attr("class", "slope")
.attr("d", d => line(d.visits))
.attr("fill", "none")
.attr("fill-opacity", 0.5)
.attr("stroke-linecap", "butt")
.attr("stroke", "#4EA376")
.attr("stroke-width", 1);
const gCircles = plots.append("g")
.attr("class", "data-points")
gCircles.append("g").attr("transform", "translate(0,2)")
.append("text")
.attr("x", d => x(1) + 4)
.attr("y", d => y(d.visits[1]))
.attr("dy", "0.35em")
.attr("text-anchor", "start")
.style("font-size", 9)
.attr("opacity", d => index === 0 ? 1 : 0)
.attr("aria-hidden", d => index === 0 ? "false" : "true")
.text(d => d.visits[1] + " visits");

gCircles.append("circle")
.attr("class", "dot")
.attr("fill","#4EA376")
.attr("cx", d => x(0))
.attr("cy", d => y(d.visits[0]))
.attr("r", 2)
.clone(true)
.attr("class", "dot")
.attr("cx", d => x(1))
.attr("cy", d => y(d.visits[1]));
plots.append("text")
.attr("class", "cat-name")
.attr("x", params.multiples.width / 2)
.attr("y", params.multiples.height)
.attr("dy", "1.5em")
.attr("text-anchor", "middle")
.style("font-size", 9)
.text(d => d.name.length > 6 ? d.name.slice(0,5) + "…" : d.name);
}
Insert cell
sharedYExtent = [0, d3.max(data.flatMap(d => d.visits))];
Insert cell
function translate(d, i) {
return `translate(
${(params.multiples.width + params.multiples.margin) * (2 * (i % params.multiples.columns) + 1)},
${(params.multiples.height + params.multiples.margin) * ((2 * Math.floor(i / params.multiples.columns)) + 1)}
)`;
}
Insert cell
mutable params = {
let output = {};
output["svg"] = {
"width": 954,
"height": 400
};
output["margin"] = {
"top": 0,
"right": 24,
"bottom": 72,
"left": 24
};

output["multiples"] = {
"margin": 8,
"width": (output["svg"]["height"] / 10),
"height": 50,
"columns": 9
};
output["plot"] = {
"x": output["margin"]["left"],
"y": output["margin"]["top"],
"width": output["svg"]["width"] - output["margin"]["left"] - output["margin"]["right"],
"height": output["svg"]["height"] - output["margin"]["top"] - output["margin"]["bottom"]
};

return output;
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

Purpose-built for displays of data

Observable is your go-to platform for exploring data and creating expressive data visualizations. Use reactive JavaScript notebooks for prototyping and a collaborative canvas for visual data exploration and dashboard creation.
Learn more