Public
Edited
May 28
Insert cell
Insert cell
d3 = require("d3@7")

Insert cell
products = [
{ date: "2023-01", name: "Προϊόν A", sales: 100 },
{ date: "2023-01", name: "Προϊόν B", sales: 80 },
{ date: "2023-01", name: "Προϊόν Γ", sales: 50 },
{ date: "2023-02", name: "Προϊόν A", sales: 120 },
{ date: "2023-02", name: "Προϊόν B", sales: 90 },
{ date: "2023-02", name: "Προϊόν Γ", sales: 70 },
{ date: "2023-03", name: "Προϊόν A", sales: 140 },
{ date: "2023-03", name: "Προϊόν B", sales: 110 },
{ date: "2023-03", name: "Προϊόν Γ", sales: 80 }
]

Insert cell
dataByDate = {
let dates = [...new Set(products.map(d => d.date))];
return dates.map(date => ({
date,
values: products
.filter(d => d.date === date)
.sort((a, b) => b.sales - a.sales)
}));
}

Insert cell
width = 600

Insert cell
height = 300

Insert cell
margin = ({ top: 40, right: 20, bottom: 20, left: 100 })

Insert cell
chart = {
const svg = d3.select(DOM.svg(width, height));

svg.append("g").attr("class", "x-axis").attr("transform", `translate(0,${margin.top})`);
svg.append("g").attr("class", "y-axis").attr("transform", `translate(${margin.left},0)`);

return svg.node();
}

Insert cell
update = (step) => {
const svg = d3.select(chart);
const current = dataByDate[step];

const x = d3.scaleLinear()
.domain([0, d3.max(current.values, d => d.sales)])
.range([margin.left, width - margin.right]);

const y = d3.scaleBand()
.domain(current.values.map(d => d.name))
.range([margin.top, height - margin.bottom])
.padding(0.1);

svg.select(".x-axis")
.transition().duration(500)
.call(d3.axisTop(x).ticks(5));

svg.select(".y-axis")
.transition().duration(500)
.call(d3.axisLeft(y));

const bars = svg.selectAll(".bar")
.data(current.values, d => d.name);

bars.enter().append("rect")
.attr("class", "bar")
.attr("x", margin.left)
.attr("height", y.bandwidth())
.attr("y", d => y(d.name))
.attr("width", d => x(d.sales) - margin.left)
.merge(bars)
.transition().duration(500)
.attr("y", d => y(d.name))
.attr("width", d => x(d.sales) - margin.left);

bars.exit().remove();
}

Insert cell
step = {
let i = 0;
const interval = setInterval(() => {
if (i >= dataByDate.length) return clearInterval(interval);
update(i);
i++;
}, 1500);
}

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