chartDynamic = {
const selmodel = SelectionModel();
const svg = d3.create('svg')
.attr('width', width)
.attr('height', height);
svg.append('g')
.attr('transform', `translate(0, ${height - margin.bottom})`)
.call(d3.axisBottom(x))
.append('text')
.attr('text-anchor', 'end')
.attr('fill', 'black')
.attr('font-size', '12px')
.attr('font-weight', 'bold')
.attr('x', width - margin.right)
.attr('y', -10)
.text('Fertility');
svg.append('g')
.attr('transform', `translate(${margin.left}, 0)`)
.call(d3.axisLeft(y))
.append('text')
.attr('transform', `translate(20, ${margin.top}) rotate(-90)`)
.attr('text-anchor', 'end')
.attr('fill', 'black')
.attr('font-size', '12px')
.attr('font-weight', 'bold')
.text('Life Expectancy');
const yearLabel = svg.append('text')
.attr('class', 'year')
.attr('x', 40)
.attr('y', height - margin.bottom - 20)
.attr('fill', '#ccc')
.attr('font-family', 'Helvetica Neue, Arial')
.attr('font-weight', 500)
.attr('font-size', 80)
.text(years[0]);
svg.append('g')
.attr('transform', `translate(${width - margin.right - 150}, 10)`)
.call(container => legend(container, selmodel));
let countries = svg
.selectAll('circle.country')
.data(dataDynamic.filter(d => d.year === years[0]), d => d.country)
.join('circle')
.attr('class', 'country')
.sort((a, b) => b.pop - a.pop)
.attr('opacity', 0.75)
.attr('fill', d => color(d.cluster))
.attr('cx', d => x(d.fertility))
.attr('cy', d => y(d.life_expect))
.attr('r', d => size(d.pop));
countries
.append('title')
.text(d => d.country);
countries
.on('mouseover', function() {
d3.select(this).attr('stroke', '#333').attr('stroke-width', 2);
})
.on('mouseout', function() {
d3.select(this).attr('stroke', null);
});
function setYear(year) {
yearLabel.text(year);
countries = countries
.data(dataDynamic.filter(d => d.year === year), d => d.country)
.join(
// Add code to customize how countries enter the scene.
// Idea: fade in from transparent and grow from zero size
// Make sure new elements have their properties properly initialized!
enter => enter.append('circle')
.attr('class', 'country'),
update => update,
// Add code to customize how countries exit the scene.
// Idea: fade out to transparent and shrink to zero size before removal
exit => exit.remove()
);
// Animate enter + update countries to current position and size
// Hint: If you modify opacity above, you probably want to update it here!
countries.transition()
.duration(1000)
.attr('cx', d => x(d.fertility))
.attr('cy', d => y(d.life_expect))
.attr('r', d => size(d.pop));
}
selmodel.on('change.chart', () => {
countries.attr('fill', d => selmodel.has(d.cluster) ? color(d.cluster) : '#ccc');
});
return Object.assign(svg.node(), { setYear });
}