- Joined
- Sep 15, 2014
- Messages
- 4,341
- Likes
- 8,855
- Degree
- 8
Here is the code for those racing bar charts you see everywhere.
This code was coded 100% with ChatGPT from scratch. I didn't write a single line of code. Here is a live example using GDP of the top 10 countries with the highest GDP up to 2022: https://www.makoboard.com/demo/d3/
There are whole Faceless YouTube channels like this that simple uses these charts: @DataIsBeautifulOfficial
Here is a video of the code running:
Here is the HTML code:
Here is the CSV that it calls (you'll need to save this as real-gdp.csv):
--
Github version of code: D3 Racing Bar Chart
--
You guys can adjust this code for whatever industry or topic you want and publish this on YouTube or as parts of your articles when creating compelling content.
This code was coded 100% with ChatGPT from scratch. I didn't write a single line of code. Here is a live example using GDP of the top 10 countries with the highest GDP up to 2022: https://www.makoboard.com/demo/d3/
There are whole Faceless YouTube channels like this that simple uses these charts: @DataIsBeautifulOfficial
Here is a video of the code running:
Here is the HTML code:
Code:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<script src="https://d3js.org/d3.v6.min.js"></script>
<style>
.axis-label {
font: 10px sans-serif;
text-anchor: middle;
}
.gdp-label {
font: 12px sans-serif;
text-anchor: start;
}
.icon {
width: 40px;
height: 40px;
}
.year-text {
font: 60px sans-serif;
text-anchor: end;
fill: lightgray;
}
</style>
</head>
<body>
<center><svg width="1024" height="500"></svg></center>
<script>
var svg = d3.select("svg"),
margin = {top: 20, right: 100, bottom: 30, left: 100},
width = +svg.attr("width") - margin.left - margin.right,
height = +svg.attr("height") - margin.top - margin.bottom;
var barPadding = 5; // Adjust this value to change the padding/margin of the bars
var intervalDuration = 300; // Default interval duration
var startDelay = 100; // Delay before the graphic starts
var xAxisLineColor = "#999999"; // Default x-axis line color
var maxLoops = 1; // Maximum number of loops
var g = svg.append("g").attr("transform", "translate(" + margin.left + "," + margin.top + ")");
var x = d3.scaleLinear().range([0, width]),
y = d3.scaleBand().range([0, height]).paddingInner(0.1).paddingOuter(0.1);
var parseTime = d3.timeParse("%Y");
// Define icons for each country (you can add more icons here as needed)
var icons = {
'USA': 'https://www.makoboard.com/img/d3/flags/com.png',
'China': 'https://www.makoboard.com/img/d3/flags/cn.png',
'India': 'https://www.makoboard.com/img/d3/flags/in.png',
'Germany': 'https://www.makoboard.com/img/d3/flags/de.png',
'UK': 'https://www.makoboard.com/img/d3/flags/co.uk.png',
'Japan': 'https://www.makoboard.com/img/d3/flags/co.jp.png',
'France': 'https://www.makoboard.com/img/d3/flags/fr.png',
'Russia': 'https://www.makoboard.com/img/d3/flags/ru.png',
'Canada': 'https://www.makoboard.com/img/d3/flags/ca.png',
'Italy': 'https://www.makoboard.com/img/d3/flags/it.png'
};
// Define custom colors for each country (you can add more colors here as needed)
var colors = {
'USA': '#3C3B6E',
'China': '#FFDE00',
'India': '#138808',
'Germany': '#DD0000',
'UK': '#C8102E',
'Japan': '#BC002D',
'France': '#0055A4',
'Russia': '#CA190C',
'Canada': '#FF0000',
'Italy': '#009246'
};
d3.csv("real-gdp.csv").then(function(data) {
data.forEach(function(d) {
d.date = parseTime(d.date);
for (const country of Object.keys(d)) {
if (country !== 'date') {
d[country] = +d[country];
}
}
});
var yearData = {};
data.forEach(function(d) {
var year = d.date.getFullYear();
if (!yearData[year]) {
yearData[year] = [];
}
for (const country of Object.keys(d)) {
if (country !== 'date' && d[country] > 0) {
yearData[year].push({country: country, gdp: d[country]});
}
}
});
var years = Object.keys(yearData).map(d => +d).sort((a, b) => a - b);
years.forEach(function(year) {
yearData[year].sort((a, b) => b.gdp - a.gdp);
yearData[year] = yearData[year].slice(0, 10); // Keep only the top 10 countries for each year
});
var firstYear = years[0];
x.domain([0, d3.max(yearData[firstYear], d => d.gdp)]);
updateYScale(yearData[firstYear]);
g.append("g")
.attr("class", "axis axis--x")
.attr("transform", "translate(0," + height + ")")
.call(d3.axisBottom(x).ticks(width / 80))
.selectAll(".tick line")
.attr("y1", -height)
.attr("stroke", xAxisLineColor);
g.append("g")
.attr("class", "axis axis--y")
.call(d3.axisLeft(y).tickSize(0).tickPadding(6));
var bars = g.selectAll(".bar")
.data(yearData[firstYear], d => d.country)
.enter().append("rect")
.attr("class", "bar")
.attr("x", x(0))
.attr("y", d => y(d.country))
.attr("width", d => x(d.gdp))
.attr("height", y.bandwidth()) // Use y.bandwidth() for bar height
.attr("fill", d => colors[d.country]);
var iconsSelection = g.selectAll(".icon")
.data(yearData[firstYear], d => d.country)
.enter().append("image")
.attr("class", "icon")
.attr("x", d => x(d.gdp) - 60) // Adjust the icon position to the right within the bar
.attr("y", d => y(d.country) + (y.bandwidth() - 40) / 2) // Center the icon vertically within the bar
.attr("width", 40)
.attr("height", 40)
.attr("href", d => icons[d.country]);
var gdpLabels = g.selectAll(".gdp-label")
.data(yearData[firstYear], d => d.country)
.enter().append("text")
.attr("class", "gdp-label")
.attr("x", d => x(d.gdp) + 5)
.attr("y", d => y(d.country) + y.bandwidth() / 2)
.attr("dy", ".35em")
.text(d => `$${d3.format(",")(Math.round(d.gdp))}B GDP`); // Format GDP values with commas and add "B"
var yearText = svg.append("text")
.attr("class", "year-text")
.attr("x", width + margin.left + margin.right - 10)
.attr("y", height - 50)
.attr("text-anchor", "end")
.text(firstYear);
function updateYScale(data) {
y.domain(data.map(d => d.country))
.range([0, height]);
}
function update(year) {
var yearDataSlice = yearData[year];
x.domain([0, d3.max(yearDataSlice, d => d.gdp)]);
updateYScale(yearDataSlice);
var xAxis = g.select(".axis--x").transition()
.duration(intervalDuration)
.call(d3.axisBottom(x).ticks(width / 80));
xAxis.selectAll(".tick line")
.attr("stroke", xAxisLineColor);
g.select(".axis--y").transition()
.duration(intervalDuration)
.call(d3.axisLeft(y).tickSize(0).tickPadding(6));
// Update bars
bars = g.selectAll(".bar").data(yearDataSlice, d => d.country);
bars.exit().transition().duration(intervalDuration).style("opacity", 0).remove();
bars.enter().append("rect")
.attr("class", "bar")
.attr("x", x(0))
.attr("y", d => y(d.country))
.attr("width", d => x(d.gdp))
.attr("height", y.bandwidth())
.attr("fill", d => colors[d.country])
.style("opacity", 0)
.transition().duration(intervalDuration).style("opacity", 1);
bars.transition()
.duration(intervalDuration)
.attr("y", d => y(d.country))
.attr("width", d => x(d.gdp))
.attr("height", y.bandwidth());
// Update icons
iconsSelection = g.selectAll(".icon").data(yearDataSlice, d => d.country);
iconsSelection.exit().transition().duration(intervalDuration).style("opacity", 0).remove();
iconsSelection.enter().append("image")
.attr("class", "icon")
.attr("x", d => x(d.gdp) - 60)
.attr("y", d => y(d.country) + (y.bandwidth() - 40) / 2)
.attr("width", 40)
.attr("height", 40)
.attr("href", d => icons[d.country])
.style("opacity", 0)
.transition().duration(intervalDuration).style("opacity", 1);
iconsSelection.transition()
.duration(intervalDuration)
.attr("x", d => x(d.gdp) - 60)
.attr("y", d => y(d.country) + (y.bandwidth() - 40) / 2);
// Update GDP labels
gdpLabels = g.selectAll(".gdp-label").data(yearDataSlice, d => d.country);
gdpLabels.exit().transition().duration(intervalDuration).style("opacity", 0).remove();
gdpLabels.enter().append("text")
.attr("class", "gdp-label")
.attr("x", d => x(d.gdp) + 5)
.attr("y", d => y(d.country) + y.bandwidth() / 2)
.attr("dy", ".35em")
.text(d => `$${d3.format(",")(Math.round(d.gdp))}B GDP`)
.style("opacity", 0)
.transition().duration(intervalDuration).style("opacity", 1);
gdpLabels.transition()
.duration(intervalDuration)
.attr("x", d => x(d.gdp) + 5)
.attr("y", d => y(d.country) + y.bandwidth() / 2)
.tween("text", function(d) {
var i = d3.interpolateNumber(+this.textContent.replace(/[^\d]/g, ''), d.gdp);
return function(t) {
this.textContent = `$${d3.format(",")(Math.round(i(t)))}B GDP`;
};
});
yearText.transition()
.duration(intervalDuration)
.text(year);
}
var currentIndex = 0;
var loopCount = 0;
setTimeout(function() {
var interval = setInterval(() => {
update(years[currentIndex]);
currentIndex = (currentIndex < years.length - 1) ? currentIndex + 1 : 0;
if (currentIndex === 0) {
loopCount++;
if (loopCount >= maxLoops) {
clearInterval(interval);
}
}
}, intervalDuration);
}, startDelay);
}).catch(function(error) {
console.error("Error loading or parsing data:", error);
});
</script>
</body>
</html>
Here is the CSV that it calls (you'll need to save this as real-gdp.csv):
Code:
date,USA,China,India,Germany,UK,Japan,France,Russia,Canada,Italy
1960,543.30,59.72,37.03,0,73.23,44.31,62.23,0,40.46,40.39
1961,563.30,50.06,39.23,0,77.74,53.51,67.46,0,40.93,44.84
1962,605.10,47.21,42.16,0,81.25,60.72,75.61,0,42.23,50.38
1963,638.60,50.71,48.42,0,86.56,69.50,84.76,0,45.03,57.71
1964,685.80,59.71,56.48,0,94.41,81.75,94.01,0,49.38,63.18
1965,743.70,70.44,59.55,0,101.82,90.95,101.54,0,54.52,67.98
1966,815.00,76.72,45.87,0,108.57,105.63,110.05,0,61.09,73.65
1967,861.70,72.88,50.13,0,113.12,123.78,118.97,0,65.67,81.13
1968,942.50,70.85,53.09,0,107.76,146.60,129.79,0,71.83,87.94
1969,1019.90,79.71,58.45,0,116.46,172.20,141.90,0,79.15,97.09
1970,1073.30,92.60,62.42,215.84,130.67,217.22,148.46,0,88.19,113.40
1971,1164.85,99.80,67.35,249.99,148.11,245.36,165.97,0,99.61,124.67
1972,1279.11,113.69,71.46,299.80,169.97,324.93,203.49,0,113.46,145.26
1973,1425.38,138.54,85.52,398.37,192.54,441.46,264.43,0,131.76,175.49
1974,1545.24,144.19,99.53,445.30,206.13,490.04,285.55,0,160.95,199.56
1975,1684.90,163.43,98.47,490.64,241.76,532.86,360.83,0,174.42,227.70
1976,1873.41,153.94,102.72,519.75,232.61,598.88,372.32,0,207.27,224.72
1977,2081.83,174.94,121.49,600.50,263.07,737.07,410.28,0,212.33,257.60
1978,2351.60,218.50,137.30,740.47,335.88,1035.61,506.71,0,219.37,315.06
1979,2627.33,263.71,152.99,881.35,438.99,1077.91,613.95,0,243.89,393.68
1980,2857.31,306.17,186.33,950.29,564.95,1129.38,701.29,0,274.78,477.26
1981,3207.04,289.58,193.49,800.47,540.77,1245.22,615.55,0,307.25,430.70
1982,3343.79,283.93,200.72,776.58,515.05,1158.73,584.88,0,314.65,427.27
1983,3634.04,304.75,218.26,770.68,489.62,1270.86,559.87,0,341.87,443.04
1984,4037.61,313.73,212.16,725.11,461.49,1345.82,530.68,0,356.72,437.89
1985,4338.98,309.84,232.51,732.53,489.29,1427.02,553.14,0,366.19,452.22
1986,4579.63,300.51,248.99,1046.26,601.45,2120.08,771.47,0,379.01,640.39
1987,4855.22,327.09,279.03,1298.18,745.16,2580.75,934.17,0,433.13,805.71
1988,5236.44,407.84,296.59,1401.23,910.12,3125.72,1018.85,554.83,509.38,891.61
1989,5641.58,456.29,296.04,1398.97,926.88,3109.46,1025.21,506.63,567.21,928.66
1990,5963.14,394.57,320.98,1771.67,1093.17,3185.90,1269.18,517.01,596.08,1181.22
1991,6158.13,413.38,270.11,1868.95,1142.80,3648.07,1269.28,517.96,612.53,1246.22
1992,6520.33,493.14,288.21,2131.57,1179.66,3980.70,1401.47,460.29,594.39,1320.16
1993,6858.56,619.11,279.30,2071.32,1061.39,4536.94,1322.82,435.08,579.05,1064.96
1994,7287.24,564.32,327.28,2205.07,1140.49,4998.80,1393.98,395.08,579.94,1099.22
1995,7639.75,734.48,360.28,2585.79,1344.24,5545.56,1601.09,395.54,605.96,1174.66
1996,8073.12,863.75,392.90,2497.24,1419.65,4923.39,1605.68,391.72,630.61,1312.43
1997,8577.55,961.60,415.87,2211.99,1560.91,4492.45,1452.88,404.93,654.99,1241.88
1998,9062.82,1029.06,421.35,2238.99,1653.69,4098.36,1503.11,270.96,634.00,1270.05
1999,9631.17,1094.01,458.82,2194.95,1687.83,4635.98,1493.15,195.91,678.41,1252.45
2000,10250.95,1211.33,468.39,1947.98,1665.53,4968.36,1365.64,259.71,744.77,1146.68
2001,10581.93,1339.40,485.44,1945.79,1649.83,4374.71,1377.66,306.60,738.98,1168.02
2002,10929.11,1470.56,514.94,2078.48,1785.73,4182.85,1501.41,345.47,760.65,1276.77
2003,11456.44,1660.28,607.70,2501.64,2054.42,4519.56,1844.54,430.35,895.54,1577.62
2004,12217.19,1955.35,709.15,2814.35,2421.53,4893.12,2119.63,591.02,1026.69,1806.54
2005,13039.20,2285.96,820.38,2846.86,2543.18,4831.47,2196.95,764.02,1173.11,1858.22
2006,13815.59,2752.12,940.26,2994.70,2708.44,4601.66,2320.54,989.93,1319.26,1949.55
2007,14474.23,3550.33,1216.74,3425.58,3090.51,4579.75,2660.59,1299.70,1468.82,2213.10
2008,14769.86,4594.34,1198.90,3745.26,2929.41,5106.68,2930.30,1660.85,1552.99,2408.66
2009,14478.06,5101.69,1341.89,3411.26,2412.84,5289.49,2700.89,1222.65,1374.63,2199.93
2010,15048.96,6087.19,1675.62,3399.67,2485.48,5759.07,2645.19,1524.92,1617.34,2136.10
2011,15599.73,7551.55,1823.05,3749.31,2663.81,6233.15,2865.16,2045.92,1793.33,2294.99
2012,16253.97,8532.19,1827.64,3527.14,2707.09,6272.36,2683.67,2208.29,1828.37,2086.96
2013,16843.19,9570.47,1856.72,3733.80,2784.85,5212.33,2811.88,2292.47,1846.60,2141.92
2014,17550.68,10475.62,2039.13,3889.09,3064.71,4896.99,2855.96,2059.24,1805.75,2162.01
2015,18206.02,11061.57,2103.59,3357.59,2927.91,4444.93,2439.19,1363.48,1556.51,1836.64
2016,18695.11,11233.31,2294.80,3469.85,2689.11,5003.68,2472.96,1276.79,1527.99,1877.07
2017,19477.34,12310.49,2651.47,3690.85,2680.15,4930.84,2595.15,1574.20,1649.27,1961.80
2018,20533.06,13894.91,2702.93,3974.44,2871.34,5040.88,2790.96,1657.33,1725.33,2091.93
2019,21380.98,14279.97,2835.61,3889.18,2851.41,5117.99,2728.87,1693.12,1743.73,2011.30
2020,21060.47,14687.74,2671.60,3887.73,2697.81,5055.59,2647.42,1493.08,1655.68,1897.46
2021,23315.08,17820.46,3150.31,4278.50,3141.51,5034.62,2959.36,1836.89,2007.47,2155.36
2022,25439.70,17963.17,3416.65,4082.47,3089.07,4256.41,2779.09,2240.42,2161.48,2049.74
--
Github version of code: D3 Racing Bar Chart
--
You guys can adjust this code for whatever industry or topic you want and publish this on YouTube or as parts of your articles when creating compelling content.
Last edited: