Published
Edited
Nov 29, 2020
1 fork
Importers
1 star
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
render_data_table(table_info)
Insert cell
Insert cell
FileAttachment("covid19_italy_province.csv")
Insert cell
data
Insert cell
data_old
Insert cell
data_old = d3.csvParse(await FileAttachment("covid19_italy_province.csv").text())
Insert cell
data.filter(d => d.TotalPositiveCases > 0)
Insert cell
data_old.filter(d => d.Date == "2020-02-25T18:00:00")
Insert cell
viewof day = Scrubber(dates.slice(0, data.length), {
delay,
loop: false,
format: d => d.toLocaleDateString()
})
Insert cell
map = {
const svg = d3
.create("svg")
.attr("width", w)
.attr("height", h)
.attr("viewBox", [0, 0, w, h])
.attr("class", "italy");

let margin = 0;

svg
.append("path")
.datum(provinces)
.attr("d", path);

const g = svg
.selectAll(".subunit")
.data(provinces.features)
.enter()
.append("path")
.attr("class", function(d) {
return "subunit";
})
.attr("d", path);

const bubble = svg
.selectAll(".bubble")
.data(data[mutable index])
.enter()
.append("circle")
.attr("transform", function(d) {
return "translate(" + projection([d.long, d.lat]) + ")";
})
.attr("class", "bubble")
.attr("fill-opacity", 0.5)
//.attr("fill", d => colorScale(+d.totale_casi))
.attr("fill", "red")
.attr("r", d => radius(+d.totale_casi));

bubble.append("title");

const tip = svg
.append("text")
.style("pointer-events", "none")
.style("text-anchor", "middle");

// tooltip
bubble.on("mouseenter", event => {
const value = event.target.__data__;
const pointer = d3.pointer(event, this);
tip
.attr("x", 300)
.attr("y", 500)
.text(
d =>
`${value.denominazione_provincia}: ${numFormat(
+value.totale_casi
)} cases`
);
});

bubble.on("mouseout", event => {
tip.text("");
});

const wrapper = html`<div class="wrapper"></div>`;
wrapper.append(svg.node());

const zoom = d3
.zoom()
.scaleExtent([0.5, 4])
.on("zoom", zoomed);

function zoomed({ transform }) {
// const transform = event.transform;
g.attr("transform", transform);
svg.attr("transform", transform);
}
svg.call(zoom);

return Object.assign(wrapper, {
update(i) {
const t = svg
.transition()
.duration(i === 0 ? 0 : delay)
.ease(d3.easeLinear);

bubble
.data(data[i])
.call(b => {
b.transition(t)
//.attr("fill", d => colorScale(+d.totale_casi))
.attr("fill", "red")
.attr("r", d => radius(+d.totale_casi));
})
.select("title")
.text(
d =>
`${d.denominazione_provincia}: ${numFormat(+d.totale_casi)} cases`
);
}
});
}
Insert cell
data
Insert cell
description = md`## Interactivity Description
In the section below, please detail what interaction techniques you employed (using the formal language from the paper), and describe what questions it allows you to ask of the chart`
Insert cell
md`### filter`
Insert cell
md`I used <b>filter</b> as the interaction technique. I used the slider function to let users filter out the data they want to see by date. People are able to see how the cases in Italy proceed after the first case was recorded. They can see the locations that have more breakouts.`
Insert cell
md`### encode`
Insert cell
md`I used <b>encode</b> to let the audience see the number of people impacted by using circles. The size of the circles shows the scale of people infected. When the user hover on it, the circle has a black outline. The name of the city and the number of cases are also showing at a specific spot of the map. People can see the specific name of the city and the number of cases.`
Insert cell
md`### Abstract/elabrate`
Insert cell
md` I am able to use <b>abstract/elabrate</b> for people to look at specific areas they want to see. This can help to answer the question of where the cases are located at when time proceeds.`
Insert cell
Insert cell
md`implementing the details of the graphs`
Insert cell
Insert cell
Insert cell
import { select } from "@jashkenas/inputs"
Insert cell
d3 = require("d3")
Insert cell
legendRadii = [10, 500, 2000, 10000]
Insert cell
map.update(index)
Insert cell
w = Math.min(width, 700)
Insert cell
h = Math.round(w * 1.2)
Insert cell
maxLegend = Math.round(maxCases / magnitude) * magnitude
Insert cell
magnitude = toMagnitude(maxCases)
Insert cell
function toMagnitude(n) {
var order = Math.floor(Math.log(n) / Math.LN10 + 0.000000001);
return Math.pow(10, order);
}
Insert cell
mutable index = 0
Insert cell
{
mutable index = dates.indexOf(day);
}
Insert cell
radius = d3
.scaleSqrt()
.domain([0, maxCases])
.range([0, maxRadius])
Insert cell
colorScale = d3
.scaleSqrt()
.domain([0, maxCases])
.range([`hsla(57, 100%, 50%, 0.36)`, `hsla(7, 100%, 50%, 0.57)`])
Insert cell
delay = 100
Insert cell
maxCases = d3.max(recentData.map(d => +d.totale_casi))
Insert cell
data = responses.map(r => d3.csvParse(r))
Insert cell
breakpoint = 500
Insert cell
maxRadius = w > breakpoint ? 30 : 18
Insert cell
recentData = data[data.length - 1]
Insert cell
responses = Promise.all(urls.map(u => fetch(u))).then(responses =>
Promise.all(responses.filter(r => r.ok).map(r => r.text()))
)
Insert cell
csvs = Promise.all(urls.map(u => fetch(u).then(u => u.text())))
Insert cell
urls = dateStrings.map(d => baseUrl.replace("DATE", d))
Insert cell
baseUrl = "https://raw.githubusercontent.com/pcm-dpc/COVID-19/master/dati-province/dpc-covid19-ita-province-DATE.csv"
Insert cell
startDate = new Date("2020-02-24T11:00:00Z")
Insert cell
endDate = new Date("2020-06-25T11:00:00Z")
Insert cell
dateStrings = dates.map(
d =>
d
.toISOString()
.replace(/-/g, '')
.split("T")[0]
)
Insert cell
dates = dateRange(startDate, endDate)
Insert cell
function dateRange(start, end) {
const duration = 1000 * 60 * 60 * 24;
const dates = [];
let ms = start * 1;
while (ms < end * 1) {
dates.push(new Date(ms));
ms += duration;
}
return dates;
}
Insert cell
allProvinces = topojson.feature(italy, italy.objects.subunits)
Insert cell
provinces = ({
...allProvinces,
// Nix Pantelleria
features: allProvinces.features.filter(
f => d3.min(f.geometry.coordinates.flat(10).filter(d => d > 30)) > 36
)
})
Insert cell
places = topojson.feature(italy, italy.objects.places)
Insert cell
sFormat = d3.format(".1s")
Insert cell
numFormat = d3.format(",")
Insert cell
path = d3.geoPath().projection(projection)
Insert cell
projection = d3
.geoAlbers()
.rotate([-12.8, 0])
.parallels([40, 50])
.fitExtent([[0, 0], [w, h]], provinces)
Insert cell
italy = FileAttachment("italy2-1.json").json()
Insert cell
topojson = require("topojson-client@3")
Insert cell
import { Scrubber } from "@mbostock/scrubber"
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