Published
Edited
Nov 11, 2020
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
bisect = {
const bisect = d3.bisector(d => d.date).left;
return mx => {
const date = x.invert(mx);
const index = bisect(desiredCountryData, date, 1);
//console.log(index)
const a = dataGroup[index - 1];
//console.log(a)
const b = dataGroup[index];
//console.log(b)
return b && (date - a.date > b.date - date) ? b : a;
};
}
Insert cell
Insert cell
Insert cell
Insert cell
chart = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])
.style("overflow", "visible");

svg.append("g")
.call(xAxis2);

svg.append("g")
.call(yAxis2);

const path = svg.append("g")
.attr("fill", "none")
.attr("stroke", "steelblue")
.attr("stroke-width", 1)
.attr("stroke-linejoin", "round")
.attr("stroke-linecap", "round")
.selectAll("path")
.data(data4.series)
.join("path")
.style("mix-blend-mode", "multiply")
.attr("d", d => line(d.values));

svg.call(hover, path);

return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
data4 = {
return {
y: "Cases",
series: data3.series.map(d => ({
name: d[0],
values: d[1]
})),
dates: data3.dates
};
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
y = d3.scaleLinear()
.domain([0, d3.max(desiredCountryData, d => d.cases)]).nice()
.range([height - margin.bottom, margin.top])
Insert cell
miniY = d3.scaleLinear()
.domain([0,d3.max(desiredCountryData, d => d.cases)]).nice()
.range([miniHeight - minimargin.bottom, minimargin.top]);
Insert cell
x = d3.scaleTime()
.domain(d3.extent(desiredCountryData, d => d.date))
.range([margin.left, width - margin.right])
Insert cell
miniX = d3.scaleTime()
.domain(d3.extent(desiredCountryData, d => d.date))
.range([minimargin.left, width - minimargin.right])
Insert cell
mainXZoom = d3.scaleTime()
.domain(d3.extent(desiredCountryData, d => d.date))
.range([margin.left, width - margin.right]);
Insert cell
Insert cell
lineMultiCases = d3.line()
.defined(d => !isNaN(d.date))
.x(d => x(d.date))
.y(d => y(d.cases));
Insert cell
miniLineMultiCases = d3.line()
.defined(d => !isNaN(d.date))
.x(d => miniX(d.date))
.y(d => miniY(d.cases));
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
function hover(svg, path) {
if ("ontouchstart" in document) svg
.style("-webkit-tap-highlight-color", "transparent")
.on("touchmove", moved)
.on("touchstart", entered)
.on("touchend", left)
else svg
.on("mousemove", moved)
.on("mouseenter", entered)
.on("mouseleave", left);

const dot = svg.append("g")
.attr("display", "none");

dot.append("circle")
.attr("r", 2.5);

dot.append("text")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("text-anchor", "middle")
.attr("y", -8);

function moved(event) {
event.preventDefault();
const pointer = d3.pointer(event, this);
const xm = x2.invert(pointer[0]);
const ym = y2.invert(pointer[1]);
const i = d3.bisectCenter(data4.dates, xm);
const s = d3.least(data4.series, d => Math.abs(d.values[i] - ym));
path.attr("stroke", d => d === s ? null : "#ddd").filter(d => d === s).raise();
dot.attr("transform", `translate(${x2(data4.dates[i])},${y2(s.values[i])})`);
dot.select("text").text(`${s.name}: ${d3.format(",")(s.values[i])} cases`);
}

function entered() {
path.style("mix-blend-mode", null).attr("stroke", "#ddd");
dot.attr("display", null);
}

function left() {
path.style("mix-blend-mode", "multiply").attr("stroke", null);
dot.attr("display", "none");
}
}
Insert cell
x2 = d3.scaleUtc()
.domain(d3.extent(data4.dates))
.range([margin.left, width - margin.right])
Insert cell
y2 = d3.scaleLinear()
.domain([0, d3.max(data4.series, d => d3.max(d.values))]).nice()
.range([height - margin.bottom, margin.top])
Insert cell
xAxis2 = g => g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(x2).ticks(width / 80).tickSizeOuter(0))
Insert cell
yAxis2 = g => g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y2))
.call(g => g.select(".domain").remove())
.call(g => g.select(".tick:last-of-type text").clone()
.attr("x", 3)
.attr("text-anchor", "start")
.attr("font-weight", "bold")
.text(data4.y))
Insert cell
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