Published
Edited
May 14, 2021
Insert cell
Insert cell
Insert cell
Insert cell
chart = {
const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);

let zupanije = svg
.append("g")
.selectAll("path")
.data(sortedFeatures)
.enter();

zupanije
.append("path")
.attr("id", (d, i) => `county-${i}`)
// .attr("class", (d, i) => `county-${i}`)
.attr("fill", (d, i) => {
//let trend = weeklyTrendData.filter((d) => d.index == i)[0].trend;
let trend = weeklyTrend.filter(d => d.index == i)[0].trend;
let retval =
trend < 0 ? negativeColorScale(trend) : positiveColorScale(trend);

return retval;
})
.attr("stroke", "black")
.attr("stroke-width", 1.2)
.attr("stroke-linejoin", "round")
.attr("d", d => path(d))
.on("click", (d, i) => {
console.log(d, projection.invert([d.offsetX, d.offsetY]));
})
.append("title")
.text((d, i) => {
//let trend = weeklyTrendData.filter(d => d.index == i)[0].trend;
let trend = weeklyTrend.filter(d => d.index == i)[0].trend;
return `${counties[i].name}\nTjedni trend: ${d3.format("+.0%")(trend)}`;
});

zupanije
.append("text")
.attr("x", (d, i) => Math.floor(projection(counties[i].label)[0]))
.attr("y", (d, i) => Math.floor(projection(counties[i].label)[1]))
.attr("class", "text-shadow")
.style("stroke", "white")
.style("stroke-width", 4)
.attr("text-anchor", "start")
.attr("alignment-baseline", "hanging")
.style("opacity", 0.9)
.style("pointer-events", "none")
.text((d, i) => {
//let trend = weeklyTrendData.filter(d => d.index == i)[0].trend;
let trend = weeklyTrend.filter(d => d.index == i)[0].trend;

return numberFormat(trend);
});

zupanije
.append("text")
.attr("x", (d, i) => Math.floor(projection(counties[i].label)[0]))
.attr("y", (d, i) => Math.floor(projection(counties[i].label)[1]))
.attr("text-anchor", "start")
.attr("alignment-baseline", "hanging")
.text((d, i) => {
//let trend = weeklyTrendData.filter(d => d.index == i)[0].trend;
let trend = weeklyTrend.filter(d => d.index == i)[0].trend;
return numberFormat(trend);
});

let tableGroups = svg
.append("g")
.attr("transform", `translate(${width * 0.85},100)`)
.selectAll("g")
.data(weeklyTrend)
.enter()
.append("g")
.on("mouseover", (event, d) => {
d3.select(`#county-${d.index}`).attr("stroke-width", 3);
d3.selectAll(`.name-${d.index}`).attr("text-decoration", "underline");
d3.selectAll(`.value-${d.index}`).attr("text-decoration", "underline");
})
.on("mouseout", (event, d) => {
var selected = d3.select(`#county-${d.index}`).attr("stroke-width", 1.2);
d3.selectAll(`.name-${d.index}`).attr("text-decoration", "none");
d3.selectAll(`.value-${d.index}`).attr("text-decoration", "none");
});

tableGroups
.append("text")
.attr("text-anchor", "end")
.attr("class", d => `name-${d.index}`)
.attr("x", 0)
.attr("y", (d, i) => i * 20)
//.text((d, i) => `${counties[i].name}: ${d3.format("+.0%")(d / 100)}`);
.text((d, i) => `${counties[d.index].name}`);

tableGroups
.append("rect")
.attr("width", 20)
.attr("height", 15)
.attr("fill", (d, i) => {
let trend = d.trend;
let retval =
trend < 0 ? negativeColorScale(trend) : positiveColorScale(trend);

return retval;
})
.attr("x", 10)
.attr("y", (d, i) => i * 20 - 12);

tableGroups
.append("text")
.attr("text-anchor", "end")
.attr("class", d => `value-${d.index}`)
.attr("x", 75)
.attr("y", (d, i) => i * 20)
.text((d, i) => `${numberFormat(d.trend)}`);

return svg.node();
}
Insert cell
Insert cell
cutoffDate
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
sortedWeeklyTrend = [...weeklyTrend].sort((a, b) => a - b)
Insert cell
covidData
Insert cell
negativeColorScale = d3
.scaleSequential()
.domain([-maxChange, 0].reverse())
.interpolator(d3.interpolateYlGn)
Insert cell
positiveColorScale = d3
.scaleSequential()
.domain([0, maxChange])
.interpolator(d3.interpolateYlOrRd)
Insert cell
maxChange = d3.max([
Math.abs(d3.min(weeklyTrend, (d) => d.trend)),
d3.max(weeklyTrend, (d) => d.trend)
])
Insert cell
cutoffDate
Insert cell
weeklyTrend = {
const retval = new Array();
weeklyIncidence.forEach((county, i) => {
retval.push({ trend: county[cutoffDate - 1], index: i });
});
return retval;
}
Insert cell
weeklyIncidence = wrangleData(covidData)
Insert cell
wrangleData = covidData => {
var weeklyIncidence = new Array(counties.length);

const window = 7;

// weeklyTrendData = {
// const retval = new Array(covidData.length);
// covidData.forEach((county, index) => {
// let lastWeek = d3.sum(county.slice(-7));
// let weekBefore = d3.sum(county.slice(-14).slice(0, 7));
// retval[index] = { trend: lastWeek / weekBefore - 1, index: index };
// });

// return retval.sort((a, b) => a.trend - b.trend);
// }

covidData.forEach((county, countyIndex) => {
weeklyIncidence[countyIndex] = new Array();
county.forEach((day, index) => {
let tempWin = index < window ? index : window;
if (tempWin == 0) weeklyIncidence[countyIndex].push(day);
else {
weeklyIncidence[countyIndex].push(
county.slice(index - tempWin, index).reduce((acc, val) => acc + val)
);
}
});
});

return weeklyIncidence;
}
Insert cell
[...weeklyIncidence[0]].reverse()
Insert cell
[...covidData[0]]
.reverse()
.slice(0, 7)
.reduce((acc, val) => acc + val)
Insert cell
array.slice(0, 1)
Insert cell
array = [1, 2, 3, 4, 5]
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell

One platform to build and deploy the best data apps

Experiment and prototype by building visualizations in live JavaScript notebooks. Collaborate with your team and decide which concepts to build out.
Use Observable Framework to build data apps locally. Use data loaders to build in any language or library, including Python, SQL, and R.
Seamlessly deploy to Observable. Test before you ship, use automatic deploy-on-commit, and ensure your projects are always up-to-date.
Learn more