Public
Edited
Apr 7, 2024
Insert cell
Insert cell
Insert cell
chart = {
let plot = d3.create('svg')
.attr('width', width + margin.left + margin.right)
.attr('height', height + margin.top + margin.bottom);

// create groups for axis, dots
plot.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top})`)
.attr('class', 'axis axis-y')
.call(yAxis);

plot.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top + height})`)
.attr('class', 'axis axis-x')
.attr('class', 'domain')
.attr('x1', 0)
.attr('x2', width)
.attr('y1', 0)
.attr('y2', 0)
.call(xAxis);


// Axis style

plot.select('.axis-y')
.selectAll('path')
.style('display', 'none');
plot.select('.axis-y')
.selectAll('line')
.style('stroke-width', 1)
.style('stroke', '#d4d4d4');

plot.select('.axis-x')
.selectAll('line')
.style('stroke-width', '2')
.style('stroke', '#222222');
plot.select('.axis-x')
.selectAll('text')
.style('font-size', '1rem');

//----------------------------------

plot.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top})`)
.attr('class', 'dots');

plot.append('g')
.attr('transform', `translate(${margin.left}, ${margin.top})`)
.attr('class', 'percentages');
plot.append('g')
.attr('transform', `translate(0, 25)`)
.attr('class', 'legend');

const plotLegend = plot.select('.legend');
plotLegend.selectAll('text').remove();
plotLegend.append('text')
.text(statement)
.attr('x', width - 5)
.attr('text-anchor', 'end')
.style('font-family', 'Helvetica, sans-serif')
.style('fill', '#222222');

const drawingData = createData();
drawDots(plot, drawingData);

return plot.node();
}
Insert cell
function drawDots(plot, data) {
const plotDataDot = plot
.select('.dots')
.selectAll('.dot')
.data(data, d => d.id);

// new dots being drawn
plotDataDot
.enter()
.append('circle')
.attr('class', d => `dot ${d.id}`)
.attr('r', 0)
.attr('cx', d => {
// in which part of the widthband
const spaceCategory = x(d.category);
const column = d.value % 10;
const spaceDecimal = scaleXDecimal(column);
return spaceCategory + spaceDecimal;
})
.attr('cy', (d,i) => i * r * 2)
.style('fill', d => color(d.category))
.transition()
.delay((d, i) => {
return 2000 + i * Math.random() * 0.5;
})
.duration(750)
.attr('r', r)
.attr('cy', d => {
const row = Math.floor(d.value/10);
return y(row) - r * 2;
})
.transition()
.delay(3000)
.duration(100)
.style("fill", d => {

return (d.compoundValue > d.categoryTarget) ? grey : color(d.category);
})
.attr("opacity", d => {

return (d.compoundValue > d.categoryTarget) ? 0.4 : 1;
});


}
Insert cell
// this function creates the data for the dots
function createData() {
const pointsArray = [];

pushToArray(categories);

// create array
function pushToArray(thisData) {
categoriesX.forEach((category) => {

const emissionsVal = thisData.get(category)[0][statement];
const targetVal = thisData.get(category)[0][target];
for (let i = 0; i < emissionsVal / unit ; i++) {

pointsArray.push({
id: `${category}_${i}`,
category: category,
value: i,
compoundValue: i * unit,
categoryValue: emissionsVal,
categoryTarget: targetVal,
type: statement,
});
}

});
}

return pointsArray;
}
Insert cell
createData()
Insert cell
Insert cell
Insert cell
unit = 40
Insert cell
Insert cell
xAxis = d3.axisBottom()
.scale(x)
.tickPadding(5);
Insert cell
yAxis = d3.axisLeft()
.scale(y)
.tickSize(-width)
.tickValues([0, 25, 50, 75, 100])
.tickPadding(5);
Insert cell
Insert cell
categoriesX = [...categories.keys()];
Insert cell
x = d3.scaleBand().domain(categoriesX).range([0, width - margin.right]).paddingInner(0.4).paddingOuter(0.5);
Insert cell
// width for each type of answer
categorySpace = x.bandwidth();
Insert cell
y = d3.scaleLinear().domain([0, 100]).range([height, 0]);
Insert cell
color = d3.scaleOrdinal(categoriesX, d3.schemeCategory10)
Insert cell
scaleXDecimal = d3.scaleBand()
.domain(d3.range(10))
.range([0, categorySpace])
.paddingInner([0]);
Insert cell
Insert cell
mutable statement = "GHG emissions incl LULUCF under BAU"
Insert cell
mutable target = "2030 target of GHG emissions incl LULUCF"
Insert cell
Insert cell
emissions = FileAttachment("Emissions_targets.csv").csv({typed: true})
Insert cell
categories2 = d3.group(
emissions.filter(d => d.Country != "World" && d.Indicator == statement), d => d.Country)
Insert cell
targets = d3.group(
emissions.filter(d => d.Country != "World" && d.Indicator == "Implied average (of conditional & unconditional) economy-wide Nationally Determined Contribution 2030 target level of " + statement.substring(6)),
d => d.Country)
Insert cell
Insert cell
Insert cell
height = 700
Insert cell
emissionsBAU = FileAttachment("ghg_emissions-tergets_BAU_byContinent-1.csv").csv({typed: true})
Insert cell
categories = d3.group(emissionsBAU, d => d.Continent)
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