Looking to build beautiful, interactive data visualizations with D3.js? This post is just what you need. We’ve gathered 100 D3.js practice problems with clear, step-by-step solutions. You’ll start with simple fundamentals like selecting elements, binding data, and creating SVG shapes.
From there, you’ll practice scales, axes, transitions, and building charts such as bar charts, line charts, and scatter plots. More advanced problems cover interactivity, tooltips, and dynamic dashboards. Every challenge is written in plain language, so you can try it on your own and then review the solution.
Ideal for beginners just getting into data visualization as well as developers preparing for front-end interviews. Pick a problem, write some code, and watch your data come to life.
Try it: 100 Javascript practice problems with solutions
1. Select the body element and change its background color to lightblue using D3.js.
html
<script>
d3.select("body").style("background-color", "lightblue");
</script>
2. Select all paragraphs on the page and set their text color to red.
html
<p>First</p><p>Second</p>
<script>
d3.selectAll("p").style("color", "red");
</script>
3. Append a new <div> element to the body with the text “Hello D3”.
html
<script>
d3.select("body").append("div").text("Hello D3");
</script>
4. Remove all elements with class “temp” using D3.
html
<div class="temp">A</div><div class="temp">B</div>
<script>
d3.selectAll(".temp").remove();
</script>
5. Use data binding to create a paragraph for each item in the array [1,2,3] and display the number.
html
<script>
d3.select("body").selectAll("p")
.data([1,2,3])
.enter()
.append("p")
.text(d => d);
</script>
6. Update the text of existing paragraphs when the data changes (enter-update-exit pattern).
html
<p>old</p><p>old</p>
<script>
let data = [10,20,30];
let p = d3.selectAll("p").data(data);
p.text(d => d);
p.enter().append("p").text(d => d);
p.exit().remove();
</script>
7. Create an SVG element with width 500 and height 300 inside a div.
html
<div id="chart"></div>
<script>
d3.select("#chart")
.append("svg")
.attr("width", 500)
.attr("height", 300);
</script>
8. Draw a circle at (100,100) with radius 50 and fill color steelblue.
html
<svg width="400" height="200"></svg>
<script>
d3.select("svg")
.append("circle")
.attr("cx", 100)
.attr("cy", 100)
.attr("r", 50)
.attr("fill", "steelblue");
</script>
9. Draw a rectangle at (50,50) with width 200 and height 100, filled orange.
html
<svg width="300" height="200"></svg>
<script>
d3.select("svg")
.append("rect")
.attr("x", 50)
.attr("y", 50)
.attr("width", 200)
.attr("height", 100)
.attr("fill", "orange");
</script>
10. Draw a line from (20,150) to (280,150) with stroke black and stroke-width 2.
html
<svg width="300" height="200"></svg>
<script>
d3.select("svg")
.append("line")
.attr("x1", 20)
.attr("y1", 150)
.attr("x2", 280)
.attr("y2", 150)
.attr("stroke", "black")
.attr("stroke-width", 2);
</script>
11. Create a linear scale mapping domain [0,100] to range [0,600] and use it to map 50.
html
<script> let scale = d3.scaleLinear() .domain([0,100]) .range([0,600]); console.log(scale(50)); // 300 </script>
12. Create a band scale for categories [“A”,”B”,”C”] with range [0,300] and padding 0.1.
html
<script>
let band = d3.scaleBand()
.domain(["A","B","C"])
.range([0,300])
.padding(0.1);
console.log(band("A")); // start position
console.log(band.bandwidth()); // width of each band
</script>
13. Draw a bar chart using data [10,20,30,40] with bars as rectangles scaled linearly.
html
<svg width="400" height="200"></svg>
<script>
let data = [10,20,30,40];
let yScale = d3.scaleLinear()
.domain([0, d3.max(data)])
.range([0, 150]);
d3.select("svg")
.selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("x", (d,i) => i*50)
.attr("y", d => 180 - yScale(d))
.attr("width", 40)
.attr("height", d => yScale(d))
.attr("fill", "steelblue");
</script>
14. Add axes to a bar chart using d3.axisLeft and d3.axisBottom.
html
<svg width="400" height="200"></svg>
<script>
let data = [10,20,30,40];
let yScale = d3.scaleLinear()
.domain([0, 40])
.range([150, 0]);
let xScale = d3.scaleBand()
.domain(d3.range(data.length))
.range([0, 400])
.padding(0.1);
let svg = d3.select("svg");
svg.append("g")
.call(d3.axisLeft(yScale));
svg.append("g")
.attr("transform", `translate(0, ${yScale(0)})`)
.call(d3.axisBottom(xScale));
</script>
15. Create a pie chart with sample data [30, 20, 50] using d3.pie and d3.arc.
html
<svg width="400" height="400"></svg>
<script>
let data = [30, 20, 50];
let pie = d3.pie()(data);
let arc = d3.arc()
.innerRadius(0)
.outerRadius(150);
let svg = d3.select("svg")
.append("g")
.attr("transform", "translate(200,200)");
svg.selectAll("path")
.data(pie)
.enter()
.append("path")
.attr("d", arc)
.attr("fill", (d,i) => ["red","green","blue"][i]);
</script>
16. Add labels to the pie chart using d3.arc().centroid() and text.
html
<svg width="400" height="400"></svg>
<script>
let data = [30, 20, 50];
let pie = d3.pie()(data);
let arc = d3.arc().innerRadius(0).outerRadius(150);
let svg = d3.select("svg").append("g").attr("transform", "translate(200,200)");
svg.selectAll("path").data(pie).enter().append("path").attr("d", arc).attr("fill", (d,i)=>["red","green","blue"][i]);
svg.selectAll("text").data(pie).enter().append("text")
.attr("transform", d => `translate(${arc.centroid(d)})`)
.attr("text-anchor", "middle")
.text(d => d.data);
</script>
17. Create a simple line chart with data points [[0,10],[50,30],[100,70],[150,90]].
html
<svg width="300" height="200"></svg>
<script>
let points = [[0,10],[50,30],[100,70],[150,90]];
let xScale = d3.scaleLinear().domain([0,150]).range([0,300]);
let yScale = d3.scaleLinear().domain([0,100]).range([150,0]);
let line = d3.line()
.x(d => xScale(d[0]))
.y(d => yScale(d[1]));
d3.select("svg").append("path")
.attr("d", line(points))
.attr("stroke", "blue")
.attr("fill", "none");
</script>
18. Add circles at each data point on the line chart.
html
<svg width="300" height="200"></svg>
<script>
let points = [[0,10],[50,30],[100,70],[150,90]];
let xScale = d3.scaleLinear().domain([0,150]).range([0,300]);
let yScale = d3.scaleLinear().domain([0,100]).range([150,0]);
d3.select("svg").selectAll("circle")
.data(points)
.enter()
.append("circle")
.attr("cx", d => xScale(d[0]))
.attr("cy", d => yScale(d[1]))
.attr("r", 5)
.attr("fill", "red");
</script>
19. Add a tooltip on hover that shows the y value of a circle.
html
<svg width="300" height="200"></svg>
<script>
let points = [[0,10],[50,30],[100,70],[150,90]];
let xScale = d3.scaleLinear().domain([0,150]).range([0,300]);
let yScale = d3.scaleLinear().domain([0,100]).range([150,0]);
d3.select("svg").selectAll("circle")
.data(points)
.enter()
.append("circle")
.attr("cx", d => xScale(d[0]))
.attr("cy", d => yScale(d[1]))
.attr("r", 5)
.attr("fill", "red")
.append("title")
.text(d => d[1]);
</script>
20. Transition a circle’s cx and cy over 1 second.
html
<svg width="400" height="200"></svg>
<script>
let circle = d3.select("svg").append("circle").attr("cx",20).attr("cy",100).attr("r",10);
circle.transition()
.duration(1000)
.attr("cx", 300)
.attr("cy", 50);
</script>
21. Apply a delay of 0.5 seconds to the transition before moving a circle.
html
<svg width="400" height="200"></svg>
<script>
d3.select("svg").append("circle").attr("cx",20).attr("cy",100).attr("r",10)
.transition()
.delay(500)
.duration(1000)
.attr("cx", 300);
</script>
22. Use easing “bounce” for a transition.
html
<svg width="400" height="200"></svg>
<script>
d3.select("svg").append("circle").attr("cx",20).attr("cy",100).attr("r",10)
.transition()
.ease(d3.easeBounce)
.duration(2000)
.attr("cx", 300);
</script>
23. Add a mouseover event that changes the fill color of a circle to orange.
html
<svg width="200" height="200"></svg>
<script>
d3.select("svg").append("circle").attr("cx",100).attr("cy",100).attr("r",30).attr("fill","blue")
.on("mouseover", function() { d3.select(this).attr("fill","orange"); })
.on("mouseout", function() { d3.select(this).attr("fill","blue"); });
</script>
24. Append text to an SVG and rotate it by 45 degrees.
html
<svg width="200" height="200"></svg>
<script>
d3.select("svg").append("text")
.attr("x", 50)
.attr("y", 100)
.text("Rotated")
.attr("transform", "rotate(45, 50, 100)");
</script>
25. Draw a group (g) and place two circles and a rectangle inside it, then translate the group.
html
<svg width="300" height="200"></svg>
<script>
let g = d3.select("svg").append("g").attr("transform", "translate(50,20)");
g.append("circle").attr("cx",30).attr("cy",30).attr("r",15).attr("fill","red");
g.append("circle").attr("cx",80).attr("cy",30).attr("r",15).attr("fill","blue");
g.append("rect").attr("x",30).attr("y",50).attr("width",50).attr("height",30).attr("fill","green");
</script>
26. Create a scatter plot with random data points (50 points).
html
<svg width="500" height="400"></svg>
<script>
let data = Array.from({length:50}, () => [Math.random()*400, Math.random()*300]);
d3.select("svg")
.selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("cx", d => d[0])
.attr("cy", d => d[1])
.attr("r", 4)
.attr("fill", "steelblue");
</script>
Try it: 100 HTML practice problems with solutions
27. Use d3.csv to load a CSV file (example assumes a local file “data.csv” with columns x,y).
html
<script>
d3.csv("data.csv").then(data => {
console.log(data);
});
</script>
28. Load a JSON file and log its content.
html
<script>
d3.json("data.json").then(data => {
console.log(data);
});
</script>
29. Draw a histogram using d3.bin (binning random normal data).
html
<svg width="500" height="300"></svg>
<script>
let data = d3.range(1000).map(() => d3.randomNormal(0,1)());
let bins = d3.bin().thresholds(20)(data);
let xScale = d3.scaleLinear().domain([-3,3]).range([50,450]);
let yScale = d3.scaleLinear().domain([0, d3.max(bins, d=>d.length)]).range([250,50]);
d3.select("svg").selectAll("rect")
.data(bins)
.enter()
.append("rect")
.attr("x", d => xScale(d.x0))
.attr("y", d => yScale(d.length))
.attr("width", d => xScale(d.x1) - xScale(d.x0) - 1)
.attr("height", d => 250 - yScale(d.length))
.attr("fill", "steelblue");
</script>
30. Create an ordinal color scale returning different colors for categories.
html
<script>
let color = d3.scaleOrdinal()
.domain(["cat","dog","bird"])
.range(["red","green","blue"]);
console.log(color("cat")); // red
</script>
31. Use a time scale to plot dates vs values.
html
<svg width="400" height="200"></svg>
<script>
let data = [{date: "2024-01-01", value:10}, {date:"2024-01-02",value:30}, {date:"2024-01-03",value:20}];
let parseDate = d3.timeParse("%Y-%m-%d");
let xScale = d3.scaleTime()
.domain(d3.extent(data, d => parseDate(d.date)))
.range([50,350]);
let yScale = d3.scaleLinear()
.domain([0, d3.max(data, d=>d.value)])
.range([150,50]);
d3.select("svg").selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("cx", d => xScale(parseDate(d.date)))
.attr("cy", d => yScale(d.value))
.attr("r",5);
</script>
32. Create a zoomable canvas area using d3.zoom on a group.
html
<svg width="400" height="300"></svg>
<script>
let svg = d3.select("svg");
let g = svg.append("g");
g.append("circle").attr("cx",200).attr("cy",150).attr("r",50).attr("fill","red");
let zoom = d3.zoom().on("zoom", (event) => {
g.attr("transform", event.transform);
});
svg.call(zoom);
</script>
33. Add a drag behavior to a circle so that it can be moved.
html
<svg width="400" height="300"></svg>
<script>
let circle = d3.select("svg").append("circle").attr("cx",100).attr("cy",100).attr("r",20).attr("fill","blue");
let drag = d3.drag()
.on("drag", (event) => {
circle.attr("cx", event.x).attr("cy", event.y);
});
circle.call(drag);
</script>
34. Draw a force‑directed graph with 5 nodes and random links.
html
<svg width="500" height="500"></svg>
<script>
let nodes = [
{id:0},{id:1},{id:2},{id:3},{id:4}
];
let links = [
{source:0,target:1},{source:1,target:2},{source:2,target:3},{source:3,target:0}
];
let simulation = d3.forceSimulation(nodes)
.force("link", d3.forceLink(links).id(d => d.id))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(250,250));
let svg = d3.select("svg");
let link = svg.append("g").selectAll("line").data(links).enter().append("line").attr("stroke","gray");
let node = svg.append("g").selectAll("circle").data(nodes).enter().append("circle").attr("r",10).attr("fill","red");
simulation.on("tick", () => {
link.attr("x1", d => d.source.x).attr("y1", d => d.source.y)
.attr("x2", d => d.target.x).attr("y2", d => d.target.y);
node.attr("cx", d => d.x).attr("cy", d => d.y);
});
</script>
35. Animate a line chart by transitioning between two data sets.
html
<svg width="300" height="200"></svg>
<button>Update</button>
<script>
let svg = d3.select("svg");
let data1 = [[0,10],[50,30],[100,70],[150,90]];
let data2 = [[0,50],[50,80],[100,20],[150,60]];
let xScale = d3.scaleLinear().domain([0,150]).range([0,300]);
let yScale = d3.scaleLinear().domain([0,100]).range([150,0]);
let lineGen = d3.line().x(d=>xScale(d[0])).y(d=>yScale(d[1]));
let path = svg.append("path").attr("fill","none").attr("stroke","blue").attr("stroke-width",2);
function draw(data) { path.attr("d", lineGen(data)); }
draw(data1);
d3.select("button").on("click", () => {
path.transition().duration(500).attrTween("d", function() {
let interpolate = d3.interpolate(data1, data2);
return function(t) { return lineGen(interpolate(t)); };
});
});
</script>
36. Create a stack bar chart using d3.stack for multiple categories.
html
<svg width="400" height="250"></svg>
<script>
let data = [
{month:"Jan", apples:10, oranges:5, bananas:8},
{month:"Feb", apples:15, oranges:10, bananas:12}
];
let keys = ["apples","oranges","bananas"];
let stack = d3.stack().keys(keys)(data);
let xScale = d3.scaleBand().domain(data.map(d=>d.month)).range([0,400]).padding(0.2);
let yScale = d3.scaleLinear().domain([0, d3.max(stack, series => d3.max(series, d=>d[1]))]).range([200,0]);
let colors = d3.scaleOrdinal().domain(keys).range(["red","orange","lightgreen"]);
let svg = d3.select("svg");
stack.forEach(series => {
svg.selectAll("rect."+series.key)
.data(series)
.enter()
.append("rect")
.attr("x", d => xScale(d.data.month))
.attr("y", d => yScale(d[1]))
.attr("width", xScale.bandwidth())
.attr("height", d => yScale(d[0]) - yScale(d[1]))
.attr("fill", colors(series.key))
.attr("class", series.key);
});
</script>
37. Use d3.axis to format ticks as percentages.
html
<svg width="300" height="200"></svg>
<script>
let yScale = d3.scaleLinear().domain([0,1]).range([150,0]);
let yAxis = d3.axisLeft(yScale).tickFormat(d3.format(".0%"));
d3.select("svg").append("g").call(yAxis);
</script>
38. Create a radial (donut) chart with inner radius 50, outer 100.
html
<svg width="300" height="300"></svg>
<script>
let data = [30, 20, 50];
let pie = d3.pie()(data);
let arc = d3.arc().innerRadius(50).outerRadius(100);
let svg = d3.select("svg").append("g").attr("transform","translate(150,150)");
svg.selectAll("path").data(pie).enter()
.append("path")
.attr("d", arc)
.attr("fill", (d,i)=>["red","green","blue"][i]);
</script>
39. Use d3.format to format a number as currency (USD).
html
<script>
let formatUSD = d3.format("$.2f");
console.log(formatUSD(1234.5)); // $1,234.50
</script>
40. Draw a map of a sample geojson (world map or simple polygon).
html
<svg width="500" height="300"></svg>
<script>
let geojson = {
type: "FeatureCollection",
features: [{
type: "Feature",
geometry: { type: "Polygon", coordinates: [[[0,0],[100,0],[100,100],[0,100],[0,0]]] }
}]
};
let projection = d3.geoMercator().fitExtent([[10,10],[490,290]], geojson);
let geoPath = d3.geoPath(projection);
d3.select("svg").append("path").attr("d", geoPath(geojson)).attr("fill", "lightblue");
</script>
41. Add a legend to a chart using SVG text and rectangles.
html
<svg width="200" height="150"></svg>
<script>
let legendData = [{label:"Series A", color:"red"},{label:"Series B", color:"blue"}];
let svg = d3.select("svg");
legendData.forEach((item,i) => {
svg.append("rect").attr("x",10).attr("y",10+i*25).attr("width",15).attr("height",15).attr("fill",item.color);
svg.append("text").attr("x",35).attr("y",23+i*25).text(item.label);
});
</script>
42. Draw multiple circles with varying opacity based on a data value.
html
<svg width="400" height="200"></svg>
<script>
let data = [0.2, 0.5, 0.9];
d3.select("svg").selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("cx", (d,i)=>100+i*100)
.attr("cy", 100)
.attr("r", 30)
.attr("fill", "blue")
.attr("opacity", d=>d);
</script>
43. Animate the opacity transition of a group of circles simultaneously.
html
<svg width="300" height="150"></svg>
<button>Fade</button>
<script>
let circles = d3.select("svg").selectAll("circle")
.data([1,2,3])
.enter()
.append("circle")
.attr("cx", (d,i)=>50+i*80)
.attr("cy", 70)
.attr("r", 20)
.attr("fill","green");
d3.select("button").on("click", () => {
circles.transition().duration(1000).attr("opacity", 0.2);
});
</script>
44. Use d3.selection.each to iterate over selected elements and log their text.
html
<div>A</div><div>B</div>
<script>
d3.selectAll("div").each(function(d,i) { console.log(d3.select(this).text()); });
</script>
45. Add a gradient to a rectangle using SVG defs and linearGradient.
html
<svg width="200" height="100"></svg>
<script>
let svg = d3.select("svg");
let defs = svg.append("defs");
let grad = defs.append("linearGradient").attr("id", "myGrad").attr("x1","0%").attr("y1","0%").attr("x2","100%").attr("y2","0%");
grad.append("stop").attr("offset","0%").attr("stop-color","red");
grad.append("stop").attr("offset","100%").attr("stop-color","blue");
svg.append("rect").attr("width",200).attr("height",100).attr("fill","url(#myGrad)");
</script>
46. Draw a dashed line with stroke-dasharray.
html
<svg width="300" height="100"></svg>
<script>
d3.select("svg").append("line")
.attr("x1",20).attr("y1",50).attr("x2",280).attr("y2",50)
.attr("stroke","black").attr("stroke-width",2)
.attr("stroke-dasharray","10,5");
</script>
47. Create a bubble chart with area proportional to value (using circle radius = sqrt(value/π)).
html
<svg width="400" height="300"></svg>
<script>
let data = [10,50,100,200];
let maxVal = d3.max(data);
let radiusScale = d3.scaleSqrt().domain([0,maxVal]).range([0,50]);
d3.select("svg").selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("cx", (d,i)=>100+i*70)
.attr("cy",150)
.attr("r", d=>radiusScale(d))
.attr("fill","steelblue");
</script>
48. Use d3.contours to generate contour lines from a 2D grid of values.
html
<svg width="300" height="200"></svg>
<script>
let grid = [[1,2,3],[2,3,4],[3,4,5]];
let contours = d3.contours().size([3,3]).thresholds([2.5])(grid);
d3.select("svg").selectAll("path")
.data(contours)
.enter()
.append("path")
.attr("d", d3.geoPath())
.attr("fill","none").attr("stroke","blue");
</script>
49. Animate a circle along a path using d3.interpolate.
html
<svg width="400" height="300"></svg>
<script>
let path = d3.select("svg").append("path")
.attr("d", "M50,50 Q200,150 350,50")
.attr("fill","none").attr("stroke","gray");
let circle = d3.select("svg").append("circle").attr("r",10).attr("fill","red");
let length = path.node().getTotalLength();
circle.transition().duration(3000)
.attrTween("transform", function() {
return function(t) {
let point = path.node().getPointAtLength(t * length);
return `translate(${point.x},${point.y})`;
};
});
</script>
50. Draw a Sankey diagram using d3-sankey (assume library included).
html
<script src="https://unpkg.com/d3-sankey@0.12.3/dist/d3-sankey.min.js"></script>
<svg width="400" height="200"></svg>
<script>
let nodes = [{name:"A"},{name:"B"},{name:"C"},{name:"D"}];
let links = [{source:0,target:1,value:5},{source:1,target:2,value:3},{source:2,target:3,value:2}];
let sankey = d3.sankey().nodeWidth(15).nodePadding(10).extent([[0,0],[400,200]]);
let graph = sankey({nodes:nodes, links:links});
let svg = d3.select("svg");
svg.append("g").selectAll("rect").data(graph.nodes).enter().append("rect")
.attr("x", d=>d.x0).attr("y", d=>d.y0).attr("width", d=>d.x1-d.x0).attr("height", d=>d.y1-d.y0)
.attr("fill","#aaa");
svg.append("g").selectAll("path").data(graph.links).enter().append("path")
.attr("d", d3.sankeyLinkHorizontal())
.attr("stroke","#333").attr("stroke-width", d=>d.width);
</script>
51. Use d3.pack to create a circle packing diagram.
html
<svg width="400" height="400"></svg>
<script>
let root = {children: [{size:10},{size:20},{size:30}]};
let pack = d3.pack().size([400,400]).padding(5);
let data = pack(d3.hierarchy(root).sum(d=>d.size));
d3.select("svg").selectAll("circle")
.data(data.descendants())
.enter()
.append("circle")
.attr("cx", d=>d.x)
.attr("cy", d=>d.y)
.attr("r", d=>d.r)
.attr("fill", "steelblue");
</script>
52. Create a tree layout (d3.tree) for hierarchical data.
html
<svg width="400" height="300"></svg>
<script>
let root = d3.hierarchy({name:"Root", children:[{name:"Child1"},{name:"Child2"}]});
let treeLayout = d3.tree().size([300,250]);
treeLayout(root);
let svg = d3.select("svg");
svg.selectAll("line").data(root.links()).enter().append("line")
.attr("x1", d=>d.source.x).attr("y1", d=>d.source.y)
.attr("x2", d=>d.target.x).attr("y2", d=>d.target.y)
.attr("stroke","black");
svg.selectAll("circle").data(root.descendants()).enter().append("circle")
.attr("cx", d=>d.x).attr("cy", d=>d.y).attr("r",5).attr("fill","red");
</script>
53. Use d3.axis to show grid lines (by adding ticks as lines).
html
<svg width="300" height="200"></svg>
<script>
let yScale = d3.scaleLinear().domain([0,100]).range([150,50]);
let yAxis = d3.axisLeft(yScale).ticks(5);
let g = d3.select("svg").append("g").call(yAxis);
g.selectAll(".tick line").attr("x2", 250).attr("stroke","gray");
</script>
54. Draw a chord diagram (using d3.chord) from a matrix.
html
<svg width="400" height="400"></svg>
<script>
let matrix = [[0,5,1],[5,0,3],[1,3,0]];
let chord = d3.chord()(matrix);
let svg = d3.select("svg");
let g = svg.append("g").attr("transform","translate(200,200)");
let ribbon = d3.ribbon().radius(150);
g.selectAll("path").data(chord)
.enter().append("path").attr("d", ribbon)
.attr("fill", "red").attr("stroke","black");
</script>
55. Use d3.timeFormat to format a date as “MM/DD/YYYY”.
html
<script>
let format = d3.timeFormat("%m/%d/%Y");
console.log(format(new Date(2024,0,1))); // 01/01/2024
</script>
Try it: CSS practice problems with solutions
56. Create a multi-line chart with different colors for each line.
html
<svg width="400" height="200"></svg>
<script>
let data = [
[{x:0,y:10},{x:1,y:20},{x:2,y:15}],
[{x:0,y:5},{x:1,y:30},{x:2,y:25}]
];
let xScale = d3.scaleLinear().domain([0,2]).range([50,350]);
let yScale = d3.scaleLinear().domain([0,30]).range([150,50]);
let line = d3.line().x(d=>xScale(d.x)).y(d=>yScale(d.y));
let colors = ["red","blue"];
data.forEach((series,i) => {
d3.select("svg").append("path")
.attr("d", line(series))
.attr("fill","none")
.attr("stroke", colors[i])
.attr("stroke-width",2);
});
</script>
57. Draw a sunburst chart using d3.partition.
html
<svg width="400" height="400"></svg>
<script>
let root = d3.hierarchy({name:"root", children:[{name:"leaf",size:1}]}).sum(d=>d.size);
let partition = d3.partition().size([2*Math.PI, 150]);
partition(root);
let arc = d3.arc().innerRadius(d=>d.y0).outerRadius(d=>d.y1).startAngle(d=>d.x0).endAngle(d=>d.x1);
let svg = d3.select("svg").append("g").attr("transform","translate(200,200)");
svg.selectAll("path").data(root.descendants())
.enter().append("path").attr("d", arc).attr("fill","steelblue");
</script>
58. Use d3.zoom to allow panning and zooming of a scatter plot.
html
<svg width="500" height="400"></svg>
<script>
let points = Array.from({length:100}, () => ({x:Math.random()*400, y:Math.random()*300}));
let g = d3.select("svg").append("g");
g.selectAll("circle").data(points).enter().append("circle")
.attr("cx", d=>d.x).attr("cy", d=>d.y).attr("r",4);
let zoom = d3.zoom().scaleExtent([0.5,5]).on("zoom", e=>g.attr("transform", e.transform));
d3.select("svg").call(zoom);
</script>
59. Add a brush to a chart to select data points.
html
<svg width="500" height="400"></svg>
<script>
let points = Array.from({length:50}, () => ({x:Math.random()*450, y:Math.random()*350}));
let svg = d3.select("svg").append("g");
svg.selectAll("circle").data(points).enter().append("circle")
.attr("cx", d=>d.x).attr("cy", d=>d.y).attr("r",5).attr("fill","blue");
let brush = d3.brush().extent([[0,0],[500,400]]).on("brush", (e) => {
let extent = e.selection;
if(extent) {
svg.selectAll("circle").attr("fill", d => (extent[0][0]<=d.x && d.x<=extent[1][0] && extent[0][1]<=d.y && d.y<=extent[1][1]) ? "red" : "blue");
}
});
svg.call(brush);
</script>
60. Animate the creation of a bar chart by increasing each bar’s height.
html
<svg width="400" height="200"></svg>
<script>
let data = [10,20,30,40];
let yScale = d3.scaleLinear().domain([0,40]).range([0,150]);
d3.select("svg").selectAll("rect")
.data(data)
.enter()
.append("rect")
.attr("x", (d,i)=>i*50)
.attr("y", 180)
.attr("width", 40)
.attr("height", 0)
.transition()
.duration(1000)
.attr("height", d=>yScale(d))
.attr("y", d=>180 - yScale(d));
</script>
61. Create a vertical stacked bar chart with groups (grouped bars).
html
<svg width="400" height="250"></svg>
<script>
let data = [{A:10,B:20},{A:15,B:25}];
let groups = ["A","B"];
let x = d3.scaleBand().domain(data.map((_,i)=>i)).range([0,400]).padding(0.2);
let inner = d3.scaleBand().domain(groups).range([0, x.bandwidth()]).padding(0.1);
let y = d3.scaleLinear().domain([0,40]).range([200,50]);
let svg = d3.select("svg");
groups.forEach(group => {
svg.selectAll(".bar-"+group)
.data(data)
.enter()
.append("rect")
.attr("x", (d,i) => x(i) + inner(group))
.attr("y", d => y(d[group]))
.attr("width", inner.bandwidth())
.attr("height", d => 200 - y(d[group]))
.attr("fill", group=="A"?"red":"blue");
});
</script>
62. Use d3.local to store per‑element data (e.g., for custom measurements).
html
<div id="test">Element</div>
<script>
let local = d3.local();
let div = d3.select("#test").node();
local.set(div, "value", 42);
console.log(local.get(div, "value")); // 42
</script>
63. Draw a gauge chart (semi‑circular) using d3.arc.
html
<svg width="200" height="200"></svg>
<script>
let backgroundArc = d3.arc().innerRadius(80).outerRadius(100).startAngle(-Math.PI/2).endAngle(Math.PI/2);
let foregroundArc = d3.arc().innerRadius(80).outerRadius(100).startAngle(-Math.PI/2).endAngle(0);
let svg = d3.select("svg").append("g").attr("transform","translate(100,100)");
svg.append("path").attr("d", backgroundArc()).attr("fill","lightgray");
svg.append("path").attr("d", foregroundArc()).attr("fill","green");
</script>
64. Use d3.axis with a log scale.
html
<svg width="300" height="200"></svg>
<script>
let logScale = d3.scaleLog().domain([1,1000]).range([50,250]);
let axis = d3.axisBottom(logScale);
d3.select("svg").append("g").attr("transform","translate(0,100)").call(axis);
</script>
65. Create a word cloud using d3-cloud (external library).
html
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3-cloud/1.2.5/d3.layout.cloud.min.js"></script>
<svg width="400" height="300"></svg>
<script>
let words = ["apple","banana","cherry","date"].map(w => ({text:w, size:20}));
d3.layout.cloud().size([400,300]).words(words)
.on("end", draw).start();
function draw(words) {
d3.select("svg").append("g").attr("transform","translate(200,150)")
.selectAll("text").data(words).enter()
.append("text").style("font-size", d=>d.size+"px")
.attr("text-anchor","middle")
.attr("transform", d=>`translate(${d.x},${d.y}) rotate(${d.rotate})`)
.text(d=>d.text);
}
</script>
66. Create a moving line chart that updates real‑time.
html
<svg width="400" height="200"></svg>
<script>
let data = [];
let xScale = d3.scaleLinear().domain([0,20]).range([0,400]);
let yScale = d3.scaleLinear().domain([0,100]).range([150,50]);
let line = d3.line().x((d,i)=>xScale(i)).y(d=>yScale(d));
let path = d3.select("svg").append("path").attr("fill","none").attr("stroke","blue");
setInterval(() => {
data.push(Math.random()*100);
if(data.length>20) data.shift();
path.attr("d", line(data));
}, 1000);
</script>
67. Draw a beeswarm plot (one‑dimensional dot plot) using force simulation on y axis.
html
<svg width="400" height="200"></svg>
<script>
let data = [10,20,30,30,40,50];
let xScale = d3.scaleLinear().domain([0,60]).range([50,350]);
let simulation = d3.forceSimulation(data)
.force("x", d3.forceX(d => xScale(d)).strength(1))
.force("collide", d3.forceCollide(5))
.stop();
for(let i=0; i<120; i++) simulation.tick();
d3.select("svg").selectAll("circle")
.data(data)
.enter()
.append("circle")
.attr("cx", d=>d.x)
.attr("cy", 100)
.attr("r", 5);
</script>
68. Create a custom interpolation between two colors for a gradient transition.
html
<svg width="200" height="60"></svg>
<button>Transition</button>
<script>
let rect = d3.select("svg").append("rect").attr("width",200).attr("height",60).attr("fill","red");
d3.select("button").on("click", () => {
rect.transition().duration(1000).attrTween("fill", function() {
return t => d3.interpolateRgb("red","blue")(t);
});
});
</script>
69. Use d3.quantile to compute quartiles.
html
<script> let numbers = [1,2,3,4,5,6,7,8,9]; let q1 = d3.quantile(numbers, 0.25); let median = d3.quantile(numbers, 0.5); let q3 = d3.quantile(numbers, 0.75); console.log(q1, median, q3); // 3,5,7 </script>
70. Draw a box plot from summary statistics.
html
<svg width="100" height="200"></svg>
<script>
let stats = {min:10, q1:20, median:35, q3:50, max:80};
let yScale = d3.scaleLinear().domain([0,100]).range([150,0]);
let svg = d3.select("svg");
let x = 50;
svg.append("line").attr("x1",x).attr("x2",x).attr("y1",yScale(stats.min)).attr("y2",yScale(stats.max)).attr("stroke","black");
svg.append("rect").attr("x",x-20).attr("y",yScale(stats.q3)).attr("width",40).attr("height", yScale(stats.q1)-yScale(stats.q3)).attr("fill","lightgray").attr("stroke","black");
svg.append("line").attr("x1",x-20).attr("x2",x+20).attr("y1",yScale(stats.median)).attr("y2",yScale(stats.median)).attr("stroke","black");
</script>
71. Use d3.random to generate a sample from a normal distribution and draw histogram.
html
<svg width="400" height="200"></svg>
<script>
let generator = d3.randomNormal(0,1);
let data = Array.from({length:500}, generator);
let bins = d3.bin().thresholds(30)(data);
let xScale = d3.scaleLinear().domain([-3,3]).range([50,350]);
let yScale = d3.scaleLinear().domain([0, d3.max(bins, d=>d.length)]).range([150,50]);
d3.select("svg").selectAll("rect").data(bins).enter().append("rect")
.attr("x", d=>xScale(d.x0))
.attr("y", d=>yScale(d.length))
.attr("width", d=>xScale(d.x1)-xScale(d.x0)-1)
.attr("height", d=>150 - yScale(d.length))
.attr("fill","steelblue");
</script>
72. Create an interactive legend that toggles visibility of chart lines.
html
<svg width="300" height="200"></svg>
<div><span id="toggleA">Toggle A</span> <span id="toggleB">Toggle B</span></div>
<script>
let dataA = [[0,10],[1,20],[2,15]];
let dataB = [[0,5],[1,30],[2,25]];
let xScale = d3.scaleLinear().domain([0,2]).range([50,250]);
let yScale = d3.scaleLinear().domain([0,30]).range([150,50]);
let line = d3.line().x(d=>xScale(d[0])).y(d=>yScale(d[1]));
let pathA = d3.select("svg").append("path").attr("d", line(dataA)).attr("fill","none").attr("stroke","red");
let pathB = d3.select("svg").append("path").attr("d", line(dataB)).attr("fill","none").attr("stroke","blue");
d3.select("#toggleA").on("click", () => pathA.style("opacity", pathA.style("opacity")==0 ? 1 : 0));
d3.select("#toggleB").on("click", () => pathB.style("opacity", pathB.style("opacity")==0 ? 1 : 0));
</script>
73. Animate the sorting of bars in a bar chart.
html
<svg width="300" height="200"></svg>
<button>Sort</button>
<script>
let data = [30,10,50,20];
let yScale = d3.scaleLinear().domain([0,50]).range([150,50]);
let svg = d3.select("svg");
let bars = svg.selectAll("rect").data(data).enter().append("rect")
.attr("x", (d,i)=>i*60)
.attr("y", d=>yScale(d))
.attr("width", 50)
.attr("height", d=>150 - yScale(d))
.attr("fill","steelblue");
let texts = svg.selectAll("text").data(data).enter().append("text")
.attr("x", (d,i)=>i*60+25)
.attr("y", d=>yScale(d)-5)
.text(d=>d);
d3.select("button").on("click", () => {
let newData = [...data].sort((a,b)=>a-b);
bars.data(newData).transition().duration(500)
.attr("x", (d,i)=>i*60)
.attr("y", d=>yScale(d))
.attr("height", d=>150 - yScale(d));
texts.data(newData).transition().duration(500)
.attr("x", (d,i)=>i*60+25)
.attr("y", d=>yScale(d)-5)
.text(d=>d);
data = newData;
});
</script>
74. Use d3.schemeCategory10 for a predefined color palette.
html
<svg width="300" height="100"></svg>
<script>
let colors = d3.scaleOrdinal(d3.schemeCategory10);
d3.select("svg").selectAll("circle")
.data([1,2,3,4,5])
.enter()
.append("circle")
.attr("cx", (d,i)=>30+i*50)
.attr("cy",50)
.attr("r",15)
.attr("fill", (d,i)=>colors(i));
</script>
75. Draw a radar chart (spider web) for multivariate data.
html
<svg width="400" height="400"></svg>
<script>
let data = {A:5, B:4, C:3, D:6};
let categories = Object.keys(data);
let angleStep = 2*Math.PI / categories.length;
let radius = 150;
let center = 200;
let points = categories.map((cat,i) => {
let val = data[cat];
let maxVal = 10;
let rad = radius * val / maxVal;
let angle = i * angleStep;
return {x: center + rad * Math.cos(angle - Math.PI/2), y: center + rad * Math.sin(angle - Math.PI/2)};
});
let line = d3.line().x(d=>d.x).y(d=>d.y);
d3.select("svg").append("path").attr("d", line(points.concat([points[0]]))).attr("fill","rgba(100,150,200,0.5)").attr("stroke","steelblue");
</script>
Try it: 100 ReactJS practice problems with solutions
76. Add animation to a path drawing (stroke‑dashoffset).
html
<svg width="300" height="200"></svg>
<script>
let linePath = d3.select("svg").append("path")
.attr("d", "M50,150 Q150,50 250,150")
.attr("fill","none").attr("stroke","red").attr("stroke-width",3);
let length = linePath.node().getTotalLength();
linePath.attr("stroke-dasharray", length).attr("stroke-dashoffset", length)
.transition().duration(2000).attr("stroke-dashoffset", 0);
</script>
77. Create a geographic projection (Albers USA) and draw state boundaries (sample).
html
<svg width="500" height="300"></svg>
<script>
let projection = d3.geoAlbersUsa().translate([250,150]).scale(800);
let geoPath = d3.geoPath(projection);
// In practice we'd load US GeoJSON here; this is a dummy:
let dummyGeo = {type:"Polygon", coordinates:[[[-120,30],[-70,30],[-70,50],[-120,50],[-120,30]]]};
d3.select("svg").append("path").attr("d", geoPath(dummyGeo)).attr("fill","lightblue");
</script>
78. Use d3.ease to animate a circle with a custom easing (elastic).
html
<svg width="400" height="200"></svg>
<script>
let circle = d3.select("svg").append("circle").attr("cx",50).attr("cy",100).attr("r",20);
circle.transition().duration(1500).ease(d3.easeElastic)
.attr("cx", 350)
.attr("cy", 100);
</script>
79. Draw a horizon chart (small multiples of area charts).
html
<svg width="300" height="150"></svg>
<script>
let data = [5,10,15,8,3];
let bands = 2;
let height = 50;
let yScale = d3.scaleLinear().domain([0,20]).range([height,0]);
let area = d3.area().x((d,i)=>i*30).y0(yScale(0)).y1(d=>yScale(d));
d3.select("svg").append("path").attr("d", area(data)).attr("fill","steelblue");
</script>
80. Use d3.timer to create a custom animation clock.
html
<svg width="400" height="200"></svg>
<script>
let circle = d3.select("svg").append("circle").attr("cx",20).attr("cy",100).attr("r",10);
let start = Date.now();
d3.timer((elapsed) => {
let t = (elapsed % 2000) / 2000;
let x = 20 + t * 300;
circle.attr("cx", x);
});
</script>
81. Generate a Voronoi diagram from random points.
html
<svg width="400" height="300"></svg>
<script>
let points = Array.from({length:20}, () => [Math.random()*400, Math.random()*300]);
let delaunay = d3.Delaunay.from(points);
let voronoi = delaunay.voronoi([0,0,400,300]);
d3.select("svg").append("g").selectAll("path")
.data(voronoi.cellPolygons())
.enter()
.append("path")
.attr("d", d => `M${d.join("L")}`)
.attr("fill","none").attr("stroke","gray");
d3.select("svg").selectAll("circle")
.data(points)
.enter()
.append("circle")
.attr("cx", d=>d[0])
.attr("cy", d=>d[1])
.attr("r",3);
</script>
82. Create a 3D‑like bar chart using perspective (manual positioning).
html
<svg width="400" height="300"></svg>
<script>
let data = [10,20,30,40];
let xOff = [0,50,100,150];
let yScale = d3.scaleLinear().domain([0,40]).range([0,150]);
data.forEach((d,i) => {
let h = yScale(d);
let g = d3.select("svg").append("g").attr("transform", `translate(${xOff[i]},200)`);
g.append("rect").attr("x",0).attr("y",-h).attr("width",30).attr("height",h).attr("fill","steelblue");
g.append("rect").attr("x",3).attr("y",-h+3).attr("width",27).attr("height",h).attr("fill","lightblue");
});
</script>
83. Draw a radial line chart (polar area chart).
html
<svg width="400" height="400"></svg>
<script>
let data = [10,20,30,40,50];
let angleStep = 2*Math.PI / data.length;
let radiusScale = d3.scaleLinear().domain([0,50]).range([0,150]);
let points = data.map((d,i) => {
let rad = radiusScale(d);
let angle = i*angleStep;
return [Math.cos(angle)*rad, Math.sin(angle)*rad];
});
let line = d3.line().x(d=>d[0]).y(d=>d[1]);
let svg = d3.select("svg").append("g").attr("transform","translate(200,200)");
svg.append("path").attr("d", line(points.concat([points[0]]))).attr("fill","rgba(100,200,100,0.5)").attr("stroke","green");
</script>
84. Animate a bar chart with data updates (changing data).
html
<svg width="400" height="200"></svg>
<button>Randomize</button>
<script>
let data = [10,20,30,40];
let yScale = d3.scaleLinear().domain([0,50]).range([0,150]);
function update(newData) {
let bars = d3.select("svg").selectAll("rect").data(newData);
bars.enter().append("rect")
.attr("x", (d,i)=>i*50)
.attr("width", 40)
.merge(bars)
.transition().duration(500)
.attr("y", d=>180 - yScale(d))
.attr("height", d=>yScale(d));
bars.exit().remove();
}
update(data);
d3.select("button").on("click", () => {
let newData = data.map(() => Math.random()*50);
update(newData);
data = newData;
});
</script>
85. Draw a calendar heatmap (monthly activity).
html
<svg width="400" height="200"></svg>
<script>
let data = Array.from({length:365}, (_,i) => ({date: new Date(2024,0,i+1), value: Math.random()}));
let color = d3.scaleSequentialLog().domain([0,1]).interpolator(d3.interpolateBlues);
let svg = d3.select("svg");
let cellSize = 5;
data.forEach((d,i) => {
let x = i % 53 * (cellSize+2);
let y = Math.floor(i / 53) * (cellSize+2);
svg.append("rect").attr("x",x).attr("y",y).attr("width",cellSize).attr("height",cellSize).attr("fill", color(d.value));
});
</script>
86. Use d3.csv to parse and visualize a CSV file inline.
html
<svg width="400" height="200"></svg>
<script>
let csvData = "x,y\n1,10\n2,20\n3,15";
let parsed = d3.csvParse(csvData);
let xScale = d3.scaleLinear().domain([1,3]).range([50,350]);
let yScale = d3.scaleLinear().domain([0,20]).range([150,50]);
d3.select("svg").selectAll("circle")
.data(parsed)
.enter()
.append("circle")
.attr("cx", d=>xScale(+d.x))
.attr("cy", d=>yScale(+d.y))
.attr("r",5);
</script>
87. Create a sankey diagram with custom node colors (library already used).
88. Draw a stacked area chart using d3.stack.
html
<svg width="400" height="200"></svg>
<script>
let data = [
{year:2020, A:10, B:5},
{year:2021, A:15, B:10}
];
let keys = ["A","B"];
let stack = d3.stack().keys(keys)(data);
let xScale = d3.scaleLinear().domain([2020,2021]).range([50,350]);
let yScale = d3.scaleLinear().domain([0, d3.max(stack, s=>d3.max(s, d=>d[1]))]).range([150,50]);
let area = d3.area().x(d=>xScale(d.data.year)).y0(d=>yScale(d[0])).y1(d=>yScale(d[1]));
let colors = d3.scaleOrdinal().domain(keys).range(["red","blue"]);
stack.forEach(series => {
d3.select("svg").append("path").attr("d", area(series)).attr("fill", colors(series.key));
});
</script>
89. Group a set of circles into a layout using d3.force (demo of forces).
html
<svg width="400" height="400"></svg>
<script>
let nodes = [{},{},{},{},{}];
let simulation = d3.forceSimulation(nodes)
.force("charge", d3.forceManyBody().strength(-50))
.force("center", d3.forceCenter(200,200));
let circles = d3.select("svg").selectAll("circle").data(nodes).enter().append("circle").attr("r",10).attr("fill","red");
simulation.on("tick", () => {
circles.attr("cx", d=>d.x).attr("cy", d=>d.y);
});
</script>
90. Use d3.axis to create a color legend for a choropleth map.
html
<svg width="300" height="100"></svg>
<script>
let color = d3.scaleLinear().domain([0,100]).range(["white","darkblue"]);
let defs = d3.select("svg").append("defs");
let linearGrad = defs.append("linearGradient").attr("id","grad").attr("x1","0%").attr("y1","0%").attr("x2","100%").attr("y2","0%");
color.ticks(5).forEach( (t,i) => linearGrad.append("stop").attr("offset", (i/4)*100+"%").attr("stop-color", color(t)));
d3.select("svg").append("rect").attr("x",10).attr("y",40).attr("width",200).attr("height",20).attr("fill","url(#grad)");
d3.select("svg").append("g").attr("transform","translate(10,60)").call(d3.axisBottom(d3.scaleLinear().domain([0,100]).range([0,200])));
</script>
91. Create a custom brush that selects circles and changes their color.
html
<svg width="400" height="400"></svg>
<script>
let points = Array.from({length:100}, () => ({x:Math.random()*380, y:Math.random()*380}));
let svg = d3.select("svg");
let circles = svg.selectAll("circle").data(points).enter().append("circle").attr("cx", d=>d.x).attr("cy", d=>d.y).attr("r",5).attr("fill","blue");
let brush = d3.brush().extent([[0,0],[400,400]]).on("end", (e) => {
if(!e.selection) return;
let [[x0,y0],[x1,y1]] = e.selection;
circles.attr("fill", d => (d.x>=x0 && d.x<=x1 && d.y>=y0 && d.y<=y1) ? "red" : "blue");
});
svg.call(brush);
</script>
92. Draw a donut chart with a label in the center showing total.
html
<svg width="200" height="200"></svg>
<script>
let data = [30,20,50];
let pie = d3.pie()(data);
let arc = d3.arc().innerRadius(50).outerRadius(80);
let svg = d3.select("svg").append("g").attr("transform","translate(100,100)");
svg.selectAll("path").data(pie).enter()
.append("path").attr("d", arc).attr("fill", (d,i)=>["red","green","blue"][i]);
let total = data.reduce((a,b)=>a+b,0);
svg.append("text").attr("text-anchor","middle").attr("dy","0.3em").text(total);
</script>
93. Create a globe (spherical projection) with a point at a given latitude/longitude.
html
<svg width="400" height="400"></svg>
<script>
let width=400, height=400;
let projection = d3.geoOrthographic().fitExtent([[10,10],[width-10,height-10]], {type:"Sphere"});
let geoPath = d3.geoPath(projection);
let svg = d3.select("svg");
svg.append("path").attr("d", geoPath({type:"Sphere"})).attr("fill","lightblue");
let point = [0,0];
let coords = projection(point);
svg.append("circle").attr("cx", coords[0]).attr("cy", coords[1]).attr("r",5).attr("fill","red");
</script>
94. Use d3.drag to allow dragging of multiple circles simultaneously with constraints.
html
<svg width="400" height="400"></svg>
<script>
let circles = d3.select("svg").selectAll("circle").data([{cx:50,cy:50},{cx:150,cy:150}]);
circles.enter().append("circle").attr("r",20).attr("fill","blue").attr("cx", d=>d.cx).attr("cy", d=>d.cy)
.call(d3.drag().on("drag", function(e) {
let newX = e.x, newY = e.y;
newX = Math.min(380, Math.max(20, newX));
newY = Math.min(380, Math.max(20, newY));
d3.select(this).attr("cx", newX).attr("cy", newY);
}));
</script>
95. Draw a line chart with confidence band (shaded area around mean).
html
<svg width="400" height="200"></svg>
<script>
let x = d3.range(10);
let mean = x.map(d=>10+Math.sin(d));
let upper = mean.map(d=>d+2);
let lower = mean.map(d=>d-2);
let xScale = d3.scaleLinear().domain([0,9]).range([50,350]);
let yScale = d3.scaleLinear().domain([0,20]).range([150,50]);
let area = d3.area().x((d,i)=>xScale(i)).y0(d=>yScale(lower[d])).y1(d=>yScale(upper[d]));
d3.select("svg").append("path").attr("d", area(d3.range(10))).attr("fill","lightblue").attr("opacity",0.5);
let line = d3.line().x((d,i)=>xScale(i)).y(d=>yScale(mean[d]));
d3.select("svg").append("path").attr("d", line(mean)).attr("fill","none").attr("stroke","blue");
</script>
96. Animate the transition of a pie chart between two datasets.
html
<svg width="400" height="400"></svg>
<button>Update</button>
<script>
let data1 = [30,20,50];
let data2 = [50,30,20];
let svg = d3.select("svg").append("g").attr("transform","translate(200,200)");
let arc = d3.arc().innerRadius(50).outerRadius(150);
function draw(data) {
let pie = d3.pie()(data);
let paths = svg.selectAll("path").data(pie);
paths.enter().append("path").attr("fill", (d,i)=>["red","green","blue"][i])
.merge(paths)
.transition().duration(500)
.attrTween("d", function(d) {
let interpolate = d3.interpolate(this._current, d);
return t => arc(interpolate(t));
});
paths.exit().remove();
svg.selectAll("path").each(function(d) { this._current = d; });
}
draw(data1);
d3.select("button").on("click", () => draw(data2));
</script>
Try it: 100 Node.js practice problems with solutions
97. Build a chord diagram with labels on the outside (using arcs and text).
html
<svg width="400" height="400"></svg>
<script>
let matrix = [[0,5,1],[5,0,3],[1,3,0]];
let chord = d3.chord()(matrix);
let svg = d3.select("svg").append("g").attr("transform","translate(200,200)");
let ribbon = d3.ribbon().radius(150);
let colors = d3.scaleOrdinal(d3.schemeCategory10);
chord.groups.forEach((group,i) => {
let start = group.startAngle, end = group.endAngle;
let arc = d3.arc().innerRadius(160).outerRadius(170).startAngle(start).endAngle(end)();
svg.append("path").attr("d", arc).attr("fill","none").attr("stroke","black");
let angle = (start + end) / 2;
let x = 180 * Math.cos(angle);
let y = 180 * Math.sin(angle);
svg.append("text").attr("x", x).attr("y", y).attr("text-anchor","middle").attr("dy",".3em").text(`Group${i+1}`);
});
svg.selectAll("path").data(chord).enter().append("path").attr("d", ribbon).attr("fill", d=>colors(d.source.index)).attr("opacity",0.7);
</script>
98. Add a double-click event that resets the zoom level.
html
<svg width="400" height="300"></svg>
<script>
let svg = d3.select("svg");
let g = svg.append("g");
g.append("circle").attr("cx",200).attr("cy",150).attr("r",50).attr("fill","red");
let zoom = d3.zoom().scaleExtent([1,5]).on("zoom", e=>g.attr("transform", e.transform));
svg.call(zoom).on("dblclick.zoom", null);
svg.on("dblclick", () => {
svg.transition().call(zoom.transform, d3.zoomIdentity);
});
</script>
99. Use d3.formatPrefix to format large numbers (e.g., 1e6 as 1M).
html
<script>
let format = d3.formatPrefix(".1", 1e6);
console.log(format(1500000)); // 1.5M
</script>
100. Draw a timeline with annotated events using circles and text.
html
<svg width="500" height="200"></svg>
<script>
let events = [{date:"2024-01-01", name:"Event A", y:80}, {date:"2024-06-01", name:"Event B", y:120}];
let parseDate = d3.timeParse("%Y-%m-%d");
let xScale = d3.scaleTime().domain([new Date(2024,0,1), new Date(2024,11,31)]).range([50,450]);
let svg = d3.select("svg");
svg.append("line").attr("x1",50).attr("y1",100).attr("x2",450).attr("y2",100).attr("stroke","black");
events.forEach(e => {
let x = xScale(parseDate(e.date));
svg.append("circle").attr("cx",x).attr("cy",e.y).attr("r",6).attr("fill","blue");
svg.append("text").attr("x",x).attr("y",e.y-10).attr("text-anchor","middle").text(e.name);
});
</script>
Final Thought
And there it is — 100 D3.js problems, and not one of them solved without a little piece of your heart tucked inside.
That’s the secret of data visualization, isn’t it? It’s never just about svg elements, scales, or transitions. It’s about love. Love for the story hiding inside the numbers. Love for the invisible becoming visible. Love for the quiet moment when a chart finally breathes and someone, somewhere, truly sees something for the first time.
You gave that love to every scatter plot, every bar, every shimmering line you drew. And D3.js — demanding, beautiful, infuriating D3 — it loved you back in the only way it knows: by making you a creator. By trusting you with its bindings and enter-update-exit patterns. By whispering, “You can build things that make people feel.”
So keep that love close. Let it spill onto dashboards, into interactive stories, across screens that today seem blank but tomorrow will glow with your vision. You’re not just a D3.js developer now — you’re a person who turns data into emotion. And the world will always, always need more of that.