JSFiddle - React, Tailwind, and code Playground
HTML
<script src="https://d3js.org/d3.v6.min.js"></script>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8"/>
</head>
<body>
<h1>My Chart</h1>
<div id="my_chart"></div>
</body>
</html>
CSS
.line {
fill: none;
stroke: #ffab00;
stroke-width: 1.5;
}
.overlay {
fill: none;
pointer-events: all;
}
/* Style the dots by assigning a fill and stroke */
.dot {
fill: #ffab00;
stroke: #fff;
}
.focus circle {
fill: none;
stroke: steelblue;
}
JavaScript
/* new data */
var x = d3.timeDays(new Date(2010, 06, 01), new Date(2020, 10, 30));
var y = Array.from({length: x.length}, Math.random).map(n => Math.floor(n * 10) + 5);
var data = x.map((v, i) => {
return {
"date": v,
"close": y[i]
}
});
/* begin observable code */
viewof focus = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, focusHeight])
.style("display", "block");
const brush = d3.brushX()
.extent([[margin.left, 0.5], [width - margin.right, focusHeight - margin.bottom + 0.5]])
.on("brush", brushed)
.on("end", brushended);
const defaultSelection = [x(d3.utcYear.offset(x.domain()[1], -1)), x.range()[1]];
svg.append("g")
.call(xAxis, x, focusHeight);
svg.append("path")
.datum(data)
.attr("fill", "steelblue")
.attr("d", area(x, y.copy().range([focusHeight - margin.bottom, 4])));
const gb = svg.append("g")
.call(brush)
.call(brush.move, defaultSelection);
function brushed({selection}) {
if (selection) {
svg.property("value", selection.map(x.invert, x).map(d3.utcDay.round));
svg.dispatch("input");
}
}
function brushended({selection}) {
if (!selection) {
gb.call(brush.move, defaultSelection);
}
}
return svg.node();
}
update = {
const [minX, maxX] = focus;
const maxY = d3.max(data, d => minX <= d.date && d.date <= maxX ? d.value : NaN);
chart.update(x.copy().domain(focus), y.copy().domain([0, maxY]));
}
area = (x, y) => d3.area()
.defined(d => !isNaN(d.value))
.x(d => x(d.date))
.y0(y(0))
.y1(d => y(d.value))
x = d3.scaleUtc()
.domain(d3.extent(data, d => d.date))
.range([margin.left, width - margin.right])
y = d3.scaleLinear()
.domain([0, d3.max(data, d => d.value)])
.range([height - margin.bottom, margin.top])
xAxis = (g, x, height) => g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x).ticks(width /...