Public
Edited
Mar 6, 2024
Insert cell
Insert cell
chart = {
// Declare the chart dimensions and margins.
const width = config.chart.width;
const height = config.chart.height;
const marginTop = config.margin.top;
const marginRight = config.margin.right;
const marginBottom = config.margin.bottom;
const marginLeft = config.margin.left;
const chartOffset = 24;

const dates = data.map((d) => d.date);

// Declare the x (horizontal position) scale.
const xAxisWidth = 0;

const band = d3
.scaleBand()
.domain(dates)
.range([marginLeft + chartOffset, width - marginRight])
.paddingInner(0.78)
.paddingOuter(0);

const halfBarWidth = band.bandwidth() / 2;
const x = d3
.scaleTime()
.domain(d3.extent(dates))
.range([
marginLeft + chartOffset + halfBarWidth,
width - marginRight - halfBarWidth
]);

// Declare the y (vertical position) scale.
const y = d3.scaleLinear(
[0, d3.max(data, (d) => d.max)],
[height - marginBottom - chartOffset, marginTop]
);

console.log(y(1) - y(2));

// Create the SVG container.
const svg = d3
.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.attr("style", "max-width: 100%; height: auto; height: intrinsic;")
.attr("style", `background: ${config.chart.fill}`);

const gAx = svg
.append("g")
.attr("class", "axis-x")
.attr("color", config.axis.color)
.attr("opacity", 0)
.attr("transform", `translate(0, ${height - marginBottom * 1.3})`)
.transition()
.duration(750)
.delay(600)
.ease(d3.easeCubic)
.call(
d3
.axisBottom(x)
.tickValues(data.map((d) => d.date))
.tickFormat(d3.utcFormat("%e %b"))
);
// Anitmate: Opacity and shift
gAx
.attr("transform", `translate(0,${height - marginBottom})`)
.attr("opacity", 1);

// // Add the y-axis, remove the domain line, add grid lines and a label.
const gAy = svg
.append("g")
.attr("class", "axis-y")
.attr("color", config.axis.color)
.attr("opacity", 0)
.attr(
"transform",
`translate(${marginLeft - halfBarWidth}, ${-marginBottom / 3})`
)
.transition()
.duration(750)
.delay(300)
.ease(d3.easeCubic)
.call(d3.axisLeft(y).ticks(height / 40));
// Anitmate: Opacity and shift
gAy
.attr("transform", `translate(${marginLeft - halfBarWidth},0)`)
.attr("opacity", 1);

// Add a rect for each bar.
const columns = svg
.append("g")
.attr("class", "columns")
.attr("fill", config.columns.fill)
.selectAll()
.data(data)
.join("rect")
.attr("x", (d) => band(d.date))
.attr("y", (d) => y(d.max))
.attr("height", 0)
.attr("width", band.bandwidth())
.attr("rx", band.bandwidth() / 2)
.attr("opacity", 0)
.transition()
.duration(750)
.delay((d, i) => 800 + i * 33)
.ease(d3.easeCubic);

// Animtate: Height and opacity
columns.attr("height", (d) => y(d.min) - y(d.max)).attr("opacity", 1);

// TODO: Animate in axis from the bottom

return svg.node();
}
Insert cell
config = ({
chart: {
height: 500,
width: 928,
fill: "#f3f4ed"
},
margin: {
top: 48,
left: 64,
bottom: 64,
right: 64
},
axis: {
color: "#8c8c86"
},
columns: {
fill: "#62625d"
}
})
Insert cell
aapl = FileAttachment("aapl.csv").csv({ typed: true })
Insert cell
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