{
const xOffset = 15;
const svgWidth = 400;
const barHeight = 25;
const radius = 18;
const standardVerticalSpacePerBar = 0;
const extraSpaceForTopBar = 335;
const extraSpaceForBottom = 120;
const svgHeight =
(dataSnake.length - 1) * standardVerticalSpacePerBar +
extraSpaceForTopBar +
extraSpaceForBottom;
const svg = d3
.create("svg")
.attr("viewBox", `0 0 ${svgWidth} ${svgHeight}`)
.attr("width", "100%")
.attr("height", svgHeight)
.style("display", "block")
.style("margin", "auto");
svg
.append("text")
.attr("x", 40)
.attr("y", 30)
.attr("text-anchor", "middle")
.style("font-size", "24px")
.style("font-weight", "bold")
.text("Global military spending in 2023 was about 8x larger")
.append("tspan")
.attr("x", 33)
.attr("dy", "1.2em")
.text("than the newly agreed annual climate finance goal*");
// Add subtitle
svg
.append("text")
.attr("x", -105) // Centered
.attr("y", 90) // Position below the title
.attr("text-anchor", "middle")
.style("font-size", "18px")
.style("font-style", "italic")
.text("Outcome of COP29. Excludes inflation.");
const secondLargestValue = dataSnake[1].num;
const xScale = d3
.scaleLinear()
.domain([0, 2440])
.range([xOffset, 100]) // svgWidth
.nice();
// Adjust startY calculation to include extra space for title and subtitle
dataSnake.forEach((dataSnake, index) => {
const startY =
index === 0
? radius * 2 + 20 + 70 // Add 40 to move the first bar down
: radius * 2 +
extraSpaceForTopBar +
(index - 1) * standardVerticalSpacePerBar +
20;
const { d, x, y } = serpentineBar(
dataSnake.num * 1,
300,
radius,
xOffset,
startY,
0
);
svg
.append("path")
.attr("d", d)
.attr("fill", "none")
//.attr("stroke", "#2f5d9e")
.attr("stroke", index === 0 ? "#2f5d9e" : "#e55592")
.attr("stroke-width", barHeight)
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "butt");
svg
.append("text")
.attr("x", xOffset - 10)
.attr("y", startY + 5)
.text(dataSnake.course)
.attr("alignment-baseline", "middle")
.style("text-anchor", "end")
.style("font-size", "18px");
// Format the labels for trillion and billion
const formattedLabel =
dataSnake.num >= 1000
? `$${(dataSnake.num / 1000).toFixed(2)} trillion`
: `$${dataSnake.num} billion`;
svg
.append("text")
.attr("x", x + 5)
.attr("y", y + 5)
.text(formattedLabel) // Use the formatted label
.attr("alignment-baseline", "middle")
.style("text-anchor", "start")
.style("font-size", "18px");
// ignore this code - was for something else
// Directly access the UK data using its known index
const ukData = dataSnake[15]; // Access the UK's data at index 15
// Calculate startY for the UK based on its position, which is index 15 in your case
const ukStartY =
radius * 2 +
extraSpaceForTopBar +
(15 - 1) * standardVerticalSpacePerBar +
20;
//Use the ukData to draw your elements
const ukResult = serpentineBar(
2534 / 107,
500,
radius,
xOffset,
ukStartY, // Correctly calculated startY based on the UK's position
0
);
//Add annotation
svg
.append("text")
.attr("x", ukResult.x + 60)
.attr("y", ukResult.y + 5)
.text(dataSnake.annotation)
.attr("alignment-baseline", "middle")
.style("text-anchor", "start")
.style("font-size", "14px");
});
//Add caption
svg
.append("text")
.attr("x", 80)
.attr("y", svgHeight - 20) // Position at the bottom
.attr("text-anchor", "middle")
.style("font-size", "14px")
.text(
"Source: Leo Hickman; Stockholm International Peace Research Institute (SIPRI) • Graphic: Yusuf Imaad Khan"
);
return svg.node();
}