Published
Edited
May 15, 2020
1 fork
1 star
Insert cell
Insert cell
Insert cell
chart = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);

lineCoords.forEach((coords, i) => {
const player = PLAYERS[i],
color = COLORS[player];

svg.selectAll(".line-" + player)
.data(coords)
.join("line")
.attr("class", "line-" + player)
.attr("x1", d => d.x1)
.attr("y1", d => d.y1)
.attr("x2", d => d.x2)
.attr("y2", d => d.y2)
.style("stroke", color)
.style("stroke-width", strokeWidth)
.attr("stroke-dasharray", l => lineLength(l) + " " + lineLength(l))
.attr("stroke-dashoffset", l => lineLength(l))
.transition()
.duration(500)
.delay((l, i) => i * 500)
.ease(d3.easeLinear)
.attr("stroke-dashoffset", 0);
});

svg.append("g").call(xAxis);

svg.append("g").call(yAxis);

return svg.node();
}
Insert cell
function lineLength(line) {
return d3.max([Math.abs(line.x1 - line.x2), Math.abs(line.y1 - line.y2)]);
}
Insert cell
lineCoords = pathCoords.map(arr =>
d3.pairs(arr, (p1, p2) => ({ x1: p1[0], y1: p1[1], x2: p2[0], y2: p2[1] }))
)
Insert cell
pathCoords = points.map(arr => getListOfCoords(line(arr)))
Insert cell
function getListOfCoords(pathCommands) {
const coords = pathCommands.slice(1).split("L");
return coords.map(d => d.split(",").map(e => +e));
}
Insert cell
Insert cell
chart2 = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height]);

const paths = svg.selectAll("path")
.data(points)
.join("path")
.attr("id", (d, i) => "path-" + PLAYERS[i])
.attr("d", line)
.attr("stroke", (d, i) => COLORS[PLAYERS[i]])
.attr("fill", "none");

// animate paths
const pathLengths = PLAYERS.map(player =>
svg.select("#path-" + player).node().getTotalLength()
);
paths.data(pathLengths)
.attr("stroke-dasharray", (l, i) => l + " " + l)
.attr("stroke-dashoffset", l => l)
.transition()
.duration(10000)
.ease(d3.easeLinear)
.attr("stroke-dashoffset", 0);

// indicator line that visually helps to compare progress
const indicator = svg.append("line")
.attr("x1", xScale(1))
.attr("y1", yScale(yScale.domain()[0]))
.attr("x2", xScale(1))
.attr("y2", yScale(yScale.domain()[1]))
.style("stroke", "black")
.transition()
.duration(10000)
.ease(d3.easeLinear)
.attr("x1", xScale(xExtent[1]))
.attr("x2", xScale(xExtent[1]));

svg.append("g").call(xAxis);

svg.append("g").call(yAxis);

return svg.node();
}
Insert cell
line = d3.line()
.x(d => xScale(d.game))
.y(d => yScale(d.cumsum))
.curve(d3.curveStepBefore)
Insert cell
yAxis = g => g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(yScale))
Insert cell
xAxis = g => g
.attr("transform", `translate(0,${height - margin.top})`)
.call(d3.axisBottom(xScale))
Insert cell
yScale = d3.scaleLinear()
.domain(yExtent)
.nice()
.rangeRound([height - margin.bottom, margin.top])
Insert cell
xScale = d3.scaleLinear()
.domain(xExtent)
.range([margin.left + 10, width - margin.right])
Insert cell
yExtent = {
let yExtent = d3.extent(d3.merge(points), d => d.cumsum);
yExtent[0] = d3.min([0, yExtent[0]]);
return yExtent;
}
Insert cell
xExtent = [1, points[0].length]
Insert cell
points = cumsum.map(arr => {
return [].slice.call(arr).map((d, i) => {
return {game: i + 1, cumsum: d};
});
})
Insert cell
cumsum = PLAYERS.map(player => d3.cumsum(data.map(d => d.points[player])))
Insert cell
data = {
let data = d3.csvParse(
await FileAttachment("romme-session@3.csv").text(),
d => ({
game: +d.Id,
points: {sophia: +d.Sophia, clara: +d.Clara, marina: +d.Marina}
})
);
data.unshift({game: 0, points: {sophia: 0, clara: 0, marina: 0}});
delete data.columns;
return data;
}
Insert cell
PLAYERS = ["sophia", "clara", "marina"]
Insert cell
COLORS = ({
sophia: "gold",
clara: "orange",
marina: "green"
})
Insert cell
margin = ({top: 20, right: 20, bottom: 30, left: 40})
Insert cell
height = 400
Insert cell
import {slider} from "@jashkenas/inputs"
Insert cell
d3 = require("d3@5", "d3-array@^2.4")
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