Published
Edited
Jul 24, 2020
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
map_spike = {
const svg = d3
.create("svg")
.attr("viewBox", [0, 0, w, h])
.attr("class", "italy");
svg.append("path")
.datum(statesOuter)
.attr("class", "outer")
.attr("d", path)
.attr("id", "usPath")
.attr("stroke", "grey")
.attr('stroke-width', '1px')
svg
.selectAll(".subunit")
.data(estado.features)
.enter()
.append("path")
.attr("stroke", "#BBB")
.attr("class", "county")
.style('stroke-width', d => {
let index = currentData.findIndex(dd => dd.z === d.properties.cod);
let value = currentData[index] ? currentData[index][confirmed_or_deaths] : 0;
return value > 0 ? "0px" : "0.25px";
})
.attr("fill", d => {
let index = currentData.findIndex(dd => dd.z == d.properties.cod);
let value = currentData[index] ? currentData[index][confirmed_or_deaths] : 0;
return value > 0 ? colorScaleFilled(value) : "#fff";
// return colorScaleFilled(value);
})
.attr("d", path)
.append("title")
.text(
d => {
let index = currentData.findIndex(dd => dd.z == d.properties.cod);
let value = currentData[index] ? currentData[index][confirmed_or_deaths] : 0;
return `${value}`;
}
)
;
svg
.selectAll("place")
.data(places.features)
.enter()
.append("circle")
// .attr("class", "place")
.attr("r", 2.5)
.attr("fill","#fff")
.attr("stroke","#000")
.attr("transform", function(d) {
return "translate(" + projection(d.geometry.coordinates) + ")";
});
let label = svg
.selectAll(".place-label")
.data(places.features)
.enter()
.append("text")
.attr("class", "place-label2")
.style('paint-order', 'stroke')
.style('stroke-width', '3')
.style('stroke', 'rgba(255,255,255,.85)')
.style('stroke-linecap', 'round')
.style('stroke-linejoin', 'round')
.attr("transform", function(d) {
return "translate(" + projection(d.geometry.coordinates) + ")";
})
.attr("dy", ".35em")
.text(function(d) {
return d.properties.name;
})
.attr("pointer-events","none")
.attr("x", function(d) {
return d.geometry.coordinates[0] > -1 ? -6 : 6;
})
.style("text-anchor", function(d) {
return d.geometry.coordinates[0] < -1 ? "start" : "end";
});
label.append("tspan")
.attr("class", "additionalnum")
.style('font-weight', 'bold')
.attr("x", d => label.x)
.attr("y", d => label.y)
.text(d => {
let index = currentData.findIndex(dd => dd.z == d.properties.cod);
let value = currentData[index] ? currentData[index][confirmed_or_deaths] : 0;

return " (" + value + ")";
})
const wrapper = html`<div class="wrapper"></div>`;
wrapper.append(svg.node());
return wrapper;
}
Insert cell
currentData = data[Object.keys(data)[Object.keys(data).length -1 - index]]
Insert cell
style = {
const c = `rgb(255, 255, 255, 0.5)`;
return html`<style>
form output {
font-weight: bold;
font-size: 14px;
}
.wrapper {
text-align: center;
}
.italy {
text-anchor: middle;
font-family: sans-serif;
font-size: 10px;
margin: 0 auto;
}
.subunit {
fill: #f4f4f4;
stroke: #999;
stroke-width: 0.5;
}
.place {
fill: rgba(0,0,0,0.8);
stroke: none;
}
.place-label, .legend-title {
font-weight: bold;
font-size: 13px;
fill: rgba(0,0,0,0.8);
}
.place-label {
text-shadow: ${c} 1px 0px 0px, ${c} 0.540302px 0.841471px 0px, ${c} -0.416147px 0.909297px 0px, ${c} -0.989992px 0.14112px 0px, ${c} -0.653644px -0.756802px 0px, ${c} 0.283662px -0.958924px 0px, ${c} 0.96017px -0.279415px 0px;
}
.bubble, .legend-bubble {
stroke-width: 0.8;
stroke: rgba(0,0,0,0.3)
}
.bubble:hover {
stroke: rgba(0,0,0,0.6);
stroke-width: 1.2;
cursor: crosshair;
}
.legend text {
fill: #000;
}
.legend-bubble {
stroke: rgba(0,0,0,0.4);
}
.legend-title {
text-anchor: start;
}
</style>`;
}
Insert cell
// 20 of margin if the bubble grows too large (like in `Foz do Iguaçu`).
projection = d3.geoMercator().fitExtent([[20, 0], [w-20, h]], estado)
Insert cell
Insert cell
legendRadii = [10, 100, 250]
Insert cell
Insert cell
w = Math.min(width, 700)
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
maxCases = {
var highestValue = 0; //keep track of highest value

//loop through array of objects
for (let key in data) {
var value = d3.max(data[key], d => d[confirmed_or_deaths]);
if (value > highestValue) {
highestValue = value;
}
}
return highestValue;
}
Insert cell
Insert cell
// unused since data from csv
data_json = await FileAttachment("pr_7days@4.json").json()
Insert cell
data = d3.nest().key(d => d.date).object(await d3.csvParse(await FileAttachment("pr_ndays@1.csv").text(), d => {
d["z"] = +d["z"];
d["c"] = +d["c"];
d["d"] = +d["d"];
return d;
}))
Insert cell
Insert cell
Insert cell
topCities = {
let mostRecent = data[Object.keys(data)[0]];

// clone and sort
return mostRecent.slice(0).sort((a,b) => b[confirmed_or_deaths] - a[confirmed_or_deaths]).slice(0,5);
}
Insert cell
places = {
let topCitiesFlat = topCities.map(d => d.z);
let updatedArray = [];
for (var i = 0; i < estado.features.length; i++) {
let flatIndex = topCitiesFlat.indexOf(estado.features[i].properties.cod);

if (flatIndex > -1) {
let city = data_city.find(d => d.city_ibge_code === topCities[flatIndex].z);
let features = {...estado.features[i]};
features.properties = {
"name": city.city,
"cod": city.city_ibge_code
};
features.geometry = {
"type" : "Point",
"coordinates" : [city.longitude, city.latitude]
};
updatedArray.push(features);
}
}
return {
"type": "FeatureCollection",
"features": updatedArray
};
}
Insert cell
Insert cell
data
Insert cell
Insert cell
Insert cell
Insert cell
statesOuter = topojson.mesh(brasil, brasil.objects["41"], (a, b) => a === b);
Insert cell
statesInner = topojson.mesh(brasil, brasil.objects["41"], (a, b) => a !== b);
Insert cell
Insert cell
Insert cell
Insert cell
import {radio} from "@jashkenas/inputs"
Insert cell
import {legend} from "@d3/color-legend"
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