Published
Edited
Jun 26, 2020
Fork of Cases Chart
Insert cell
Insert cell
chart = {
const svg = d3.create("svg")
.attr("viewBox", [0, 0, width, height])
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("stroke-miterlimit", 1);

const gradient = DOM.uid();
svg.append("linearGradient")
.attr("id", gradient.id)
.attr("gradientUnits", "userSpaceOnUse")
.attr("x1", 0)
.attr("y1", 0)
.attr("x2", 0)
.attr("y2", height)
.selectAll("stop")
.data([
{offset: 0, color: negativeColor},
{offset: y(threshold) / height, color: negativeColor},
{offset: y(threshold) / height, color: positiveColor},
{offset: 1, color: positiveColor}
])
.join("stop")
.attr("offset", d => d.offset)
.attr("stop-color", d => d.color);
svg.append("g")
.call(xAxis)
.selectAll("text")
.attr("color", "gray")
.attr("font-size", 12);

svg.append("g")
.call(yAxis)
.selectAll("text")
.attr("color", "gray")
.attr("font-size", 18);

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

svg.append("path")
.attr("fill", "none")
.attr("stroke", gradient)
.attr("stroke-width", 1.5)
.attr("d", line(data));
if (!mutable lookup) mutable lookup = new Date(data[0][0]);
const bar = svg
.append("line") // vertical moving line
.attr("style", "stroke-width:1")
.attr('stroke', "#910000")
// .attr("style", 'gray')
.attr("y2", height*0.94)
.attr("x1", x(mutable lookup))
.attr("x2", x(mutable lookup));
const legendData = svg
.append("text")
.style("font", "22px sans-serif")
.attr("x", 10)
.attr("y", 100);
const legendR = svg
.append("text")
.style("font", "22px sans-serif")
.attr("x", 10)
.attr("y", 125);
const marker = svg
.append("circle")
.attr("r", 3)
.attr("cx", -100)
.attr("fill", "black")
.attr("fill-opacity", 0)//circle hidden
const formatTime = d3.utcFormat("%d/%m/%Y");
function update(date) {
const i = bisect.right(data, date);
if (i < data.length && i > 0) {
legendData.text(`${formatTime(new Date(data[i][0]))}`);
legendR.text(`Casos: ${data[i][1]}`);
marker.attr("cx", x(new Date(data[i][0]))).attr("cy", y(data[i][1]));
bar.attr("stroke", negativeColor);
legendData.attr("x", (i > data.length/2)? x(new Date(data[i][0])) - 5 : x(new Date(data[i][0])))
legendData.attr("text-anchor", (i > data.length/2)? "end" : "start")
legendR.attr("x", (i > data.length/2)? x(new Date(data[i][0])) - 5 : x(new Date(data[i][0])))
legendR.attr("text-anchor", (i > data.length/2)? "end" : "start")
}
mutable lookup = new Date(date);
bar.attr("x1", x(mutable lookup)).attr("x2", x(mutable lookup));
//https://observablehq.com/@d3/index-chart --> line with range
}
svg.on("mousemove click touchmove", function() {
const m = d3.mouse(this);
update(x.invert(m[0]));
});
update(mutable lookup);
return svg.node();
}
Insert cell
mutable lookup = null
Insert cell
bisect = d3.bisector(d => new Date(d[0]))
Insert cell
positiveColor = "#910000" //#861657
Insert cell
// negativeColor = "darkred"
Insert cell
negativeColor = "#910000"
Insert cell
threshold = 1
Insert cell
file = "https://hackcovid.s3-us-west-2.amazonaws.com/data/data_new_cases.json"
Insert cell
data_raw = Object.assign(await d3.json(file, d3.autoType), {y: "↑ Mortes por dia"})
Insert cell
state = "SP"
Insert cell
data = data_raw.filter(d => d.state_code === state)[0].confirmed
Insert cell
line = d3.line()
.x(d => x(new Date(d[0])))
.y(d => y(d[1]))
Insert cell
x = d3.scaleUtc()
.domain(d3.extent(data, d => new Date(d[0])))
.range([margin.left, width - margin.right])
Insert cell
y = d3.scaleLinear() //scaleLinear domain([-1, ]) //scaleLog() domain([1, ])
.domain([0, d3.max(data, d => d[1])])
.range([height - margin.bottom, margin.top])
.clamp(true)
Insert cell
xAxis = g => g
.attr("transform", `translate(0,${height - margin.bottom})`)
// .call(d3.axisBottom(x).ticks(width / 80))
.call(d3.axisBottom(x).ticks(4))
.call(g => g.select(".domain").remove())
Insert cell
yAxis = g => g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(y).ticks(5, ",d"))
.call(g => g.selectAll(".tick line") // horizontal line
.select(function() { return this.parentNode.appendChild(this.cloneNode()); })
.attr("stroke-opacity", d => d === 1 ? null : 0.1) // if value is 1 opacity is different
.attr("stroke-width", 1.8)
.attr("stroke", 'darkgray')
.attr("x2", width - margin.left - margin.right))
.call(g => g.select(".domain").remove())


Insert cell
grid = g => g
.attr("stroke", "currentColor")
.attr("stroke-opacity", 0.1)
.attr("stroke-width", 0.5)
.call(g => g.append("g")
.selectAll("line")
.data(x.ticks())
.join("line")
.attr("x1", d => 0.5 + x(d))
.attr("x2", d => 0.5 + x(d))
.attr("y1", margin.top)
.attr("y2", height - margin.bottom))
.call(g => g.append("g")
.selectAll("line")
.data(y.ticks())
.join("line")
.attr("y1", d => 0.5 + y(d))
.attr("y2", d => 0.5 + y(d))
.attr("x1", margin.left)
.attr("x2", width - margin.right));
Insert cell
height = 600
Insert cell
width = 600
Insert cell
margin = {
if (max_value > 100000) {
return ({top: 20, right: 30, bottom: 30, left: 75})
}
else if (max_value > 10000) {
return ({top: 20, right: 30, bottom: 30, left: 65})
} else {
return ({top: 20, right: 30, bottom: 30, left: 55})
}
}
Insert cell
max_value = d3.max(data, d => d[1])
Insert cell
d3.timeFormatDefaultLocale(locale);
Insert cell
Insert cell
d3 = require("d3@5")
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