<!DOCTYPE html> <html lang="en"> <head> <meta charset="utf-8"> <title>Vertical Bar Chart</title> <script src="https://d3js.org/d3.v7.js"></script> </head> <body> <svg></svg> <p></p> <button type="button" onclick="add()">Add bar</button> <button type="button" onclick="remove()">Remove bar</button> <script> // Create svg and initial bars const w = 400; const h = 300; const margin = {top: 25, right: 0, bottom: 25, left: 25}; const innerWidth = w - margin.left - margin.right; const innerHeight = h - margin.top - margin.bottom; const svg = d3.select("svg") .attr("width", w) .attr("height", h); svg.append("rect") .attr("x", 0) .attr("y", 0) .attr("width", w) .attr("height", h) .attr("fill", "lightblue"); const bardata = [300, 100, 150, 220, 70, 270]; const xScale = d3.scaleBand() .domain(d3.range(bardata.length)) .range([0, innerWidth]) .paddingInner(.1); const yScale = d3.scaleLinear() .domain([0, 400]) // use fixed y-scale if possible .range([innerHeight, 0]) const xAxis = d3.axisBottom() .scale(xScale); const yAxis = d3.axisLeft() .scale(yScale); const bars = svg.append("g") .attr("id", "plot") .attr("transform", `translate (${margin.left}, ${margin.top})`) .selectAll("rect") .data(bardata); bars.enter().append("rect") .attr("x", (d, i) => xScale(i)) .attr("y", d => yScale(d)) .attr("width", xScale.bandwidth()) .attr("height", d => innerHeight - yScale(d)) .attr("fill", "blue"); svg.append("g") .attr("class", "xAxis") .attr("transform", `translate (${margin.left}, ${h - margin.bottom})`) .call(xAxis); svg.append("g") .attr("class", "yAxis") .attr("transform", `translate (${margin.left}, ${margin.top})`) .call(yAxis); // General Update Pattern function update(data) { xScale.domain(d3.range(data.length)); const bars = svg.select("#plot") .selectAll("rect") .data(data); const paddingpix = xScale.padding()*xScale.bandwidth()/(1 - xScale.padding()) bars.enter().append("rect") .attr("x", innerWidth + paddingpix) // new bar on the right .attr("y", d => yScale(d)) .attr("width", xScale.bandwidth()) .attr("height", d => innerHeight - yScale(d)) .attr("fill", "orange") .merge(bars) .transition() // all bars more into place .duration(2000) .ease(d3.easeLinear) .attr("x", (d, i) => xScale(i)) .attr("y", d => yScale(d)) .attr("width", xScale.bandwidth()) .attr("height", d => innerHeight - yScale(d)) .transition() // all bars turn blue .duration(2000) .ease(d3.easeLinear) .attr("fill", "blue"); bars.exit() .transition() .duration(2000) .ease(d3.easeLinear) .attr("x", innerWidth + paddingpix) .remove(); svg.select(".xAxis") .transition() .duration(2000) .ease(d3.easeLinear) .call(xAxis); } function add() { const newvalue = Math.floor(Math.random()*400); bardata.push(newvalue); update(bardata); } function remove() { bardata.pop(); update(bardata); }; </script> </body> </html>