Published
Edited
Jun 30, 2020
3 forks
17 stars
Insert cell
Insert cell
Insert cell
chart = {
replay;
const svg = d3.create('svg')
.attr('viewBox', [0, 0, width, height]);
svg.append('g').call(xAxis);
svg.selectAll('.line-decade')
.data(x.ticks())
.join('line')
.attr('class', 'line-decade')
.attr('x1', d => x(d))
.attr('x2', d => x(d))
.attr('y1', 10)
.attr('y2', height - margin.top)
.attr('stroke-width', 1)
.attr('stroke', 'lightgray');
svg.selectAll('.label-family')
.data(families)
.join('text')
.attr('class', 'label-family')
.attr('x', 0)
.attr('y', d => y(d))
.attr('alignment-baseline', 'middle')
.text(d => d);
const simulation = d3.forceSimulation(data)
.force('x', d3.forceX((d) => x(d.date)).strength(5))
.force('y', d3.forceY((d) => y(d.family)))
.force('collide', d3.forceCollide(radius + padding))
.stop();
svg.selectAll('circle')
.data(data)
.join('circle')
.attr('cx', (d) => x(d.date))
.attr('cy', (d) => y(d.family))
.attr('r', radius)
.attr('fill', (d) => color(d.family))
.append('title')
.text(d => `${d.party} in ${d.country} (${d.date.getFullYear()})`);
for(let i = 0; i<120; i++) {
simulation.tick();

svg.selectAll('circle')
.data(data)
.transition()
.duration(1200)
.ease(d3.easeLinear)
.attr('cx', (d) => d.x)
.attr('cy', (d) => d.y);

yield svg.node();
}
}
Insert cell
color = d3.scaleOrdinal()
.domain(families)
.range(d3.schemeTableau10)
Insert cell
y = d3.scaleBand()
.domain(families)
.range([height + margin.bottom, margin.top])
Insert cell
xAxis = g => g
.attr('transform', `translate(0,${height - margin.top})`)
.call(d3.axisBottom(x))
Insert cell
x = d3.scaleTime()
.domain(timeExtent)
.nice()
.range([margin.left, width - margin.right])
Insert cell
timeExtent = {
const dates = data.map((d) => d.date).sort(d3.ascending);
return [dates[0], dates[dates.length - 1]];
}
Insert cell
data = rawData.filter((d) => families.includes(d.family))
Insert cell
families = ['con', 'soc', 'lib']
Insert cell
rawData = {
const parseTime = d3.timeParse('%Y-%m-%d');
return d3.csvParse(
await FileAttachment('parlgov2018.csv').text(),
d => ({
party: d.party_name_english,
date: parseTime(d.election_date),
country: d.country_name,
family: d.family_name_short,
share: +d.vote_share,
currentShare: +d.most_recent_vote_share
})
);
}
Insert cell
margin = ({
left: 50,
right: 30,
top: 50,
bottom: 30
})
Insert cell
padding = 1.5
Insert cell
radius = 3.5
Insert cell
height = 400
Insert cell
d3 = require("d3@5")
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