Published
Edited
Oct 18, 2020
1 fork
Insert cell
Insert cell
chart = {
let svg = d3.select(DOM.svg(width, height)).style("overflow", "visible");
svg.append("path").classed("line", true).datum(dataset).attr("d", line).attr("fill", "none").attr("stroke-width", 1).attr("stroke", "green");
let tooltip = svg.append("g");
svg.on("mousemove", function(){
let [mousex, mousey] = d3.mouse(this);
let {date, close} = bisect(mousex);
let y = vertScale(close),
x = horzScale(date);
tooltip.attr("transform", `translate(${x}, ${y})`).call(callout, `${formatTime(date)}:${close}`)
})
.on("mouseout", function(){
tooltip.style("display", "none")
})
//Add Axis
svg.append("g").classed("axis x", true).call(horzAxis)
svg.append("g").classed("axis y", true).call(vertAxis)
return svg.node();
}
Insert cell
callout = (g, value) => {
if(!value){
return g.style("display", "none");
}

g.style("display", null)
.style("pointer-events", "none")
.style("font", "10px sans-serif");

const path = g.selectAll("path")
.data([null])
.join("path")
.attr("fill", "white")
.attr("stroke", "orange");

const text = g.selectAll("text")
.data([null])
.join("text")
.call(text => text
.selectAll("tspan")
.data((value + "").split(":"))
.join("tspan")
.attr("x", 0)
.attr("y", (d, i) => `${i * 1.1}em`)
.style("font-weight", (_, i) => i ? null : "bold")
.text(d => d));

const {x, y, width: w, height: h} = text.node().getBBox();
text.attr("transform", `translate(${-w/2},${15 - y})`);
path.attr("d", `M${-w / 2 - 10},5H-5l5,-5l5,5H${w / 2 + 10}v${h + 20}h-${w + 20}z`);
}
Insert cell
Insert cell
Insert cell
dataset = d3.csvParse(await FileAttachment("aapl.csv").text(), d3.autoType)
Insert cell
width = 900
Insert cell
height = 400
Insert cell
margin = ({top:10, right:10, bottom:40, left:40})
Insert cell
horzScale = d3.scaleUtc(d3.extent(dataset, (d)=>d.date), [margin.left, width-margin.right])
Insert cell
vertScale = d3.scaleLinear([0, d3.max(dataset, (d)=>d.close)], [height - margin.bottom, margin.top])
Insert cell
horzAxis = (g)=>g.call(d3.axisBottom(horzScale).ticks(width / 80).tickSizeOuter(0)).attr("transform", `translate(0, ${height-margin.bottom})`)
Insert cell
vertAxis = (g)=>g.call(d3.axisLeft(vertScale))
.attr("transform", `translate(${margin.left}, 0)`).select(".domain").remove()
Insert cell
line = d3.line().x((d)=>horzScale(d.date)).y((d)=>vertScale(d.close))
Insert cell
bisect = {
let bisect= d3.bisector((d)=>d.date).right;
return (mx)=>{
let date = horzScale.invert(mx);
let index = bisect(dataset, date);
return dataset[index];
}
}
Insert cell
formatTime = d3.timeFormat("%B %d, %Y")
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