Published
Edited
Sep 23, 2020
4 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
map = {
const svg = d3
.create("svg")
.attr("width", w)
.attr("height", h)
.attr("viewBox", [0, 0, w, h])
.attr("class", "italy");
svg
.selectAll(".subunit")
.data(provinces.features)
.enter()
.append("path")
.attr("class", function(d) {
return "subunit";
})
.attr("d", path);
let bubble;
let espinho;
let yScale = d3.scaleSqrt([0, d3.max(recentData, d => d[confirmed_or_deaths])], [0, 80])

if (scale === "bolhas") {
bubble = svg
.selectAll(".bubble")
.data(currentData)
.enter()
.append("circle")
.attr("transform", function(d) {
return "translate(" + projection([d.longitude, d.latitude]) + ")";
})
.attr("class", "bubble")
.attr("fill-opacity", 0.5)
.attr("fill", d => colorScale(d[confirmed_or_deaths]))
.attr("r", d => radius(d[confirmed_or_deaths]));
bubble.append("title");
const legend = svg
.append("g")
.attr("class", "legend")
.attr("fill", "#777")
.attr(
"transform",
`translate(${w > breakpoint ? [10, h - 25] : [10, h - 25]})`
);
legend
.append("text")
.attr("class", "legend-title")
.text("No. casos confirmados")
.attr("dy", -maxRadius * 3.0);

const legendBubbles = legend
.selectAll("g")
.data(legendRadii)
.join("g");

let margin = 0;
legendBubbles
.attr("transform", (d, i) => {
margin += i === 0 ? 0 : radius(legendBubbles.data()[i - 1]) * 2 + 15;
return `translate(${margin + radius(d)}, 0)`;
})
.append("circle")
.attr("class", "legend-bubble")
.attr("fill", d => colorScale(d))
.attr("cy", d => -radius(d))
.attr("r", radius);

legendBubbles
.append("text")
.attr("dy", "1.3em")
.text(w > breakpoint ? numFormat : sFormat);
} else {
const gradient = DOM.uid();

espinho = svg
.selectAll("polyline")
.data(currentData)
.enter()
.append("polyline")
.attr("class", "polyline")
.attr("id", d => d.id)
.attr("points", d => {
const _d = currentData.find(dd => dd.city_ibge_code === d.city_ibge_code);
const h = (_d !== undefined)? yScale(_d[confirmed_or_deaths]) : 0;
const projectionxy = projection([d.longitude, d.latitude]);
const x = projectionxy[0];
const y = projectionxy[1];
return `${x - 4},${y} ${x},${y - h} ${x + 4},${y}`;
})
.attr("stroke", d=> colorScale(+d[confirmed_or_deaths]))
.attr("fill", gradient);

const colors = d3.scaleOrdinal([100,0],['#f3f3f3','#cc0000'])

const gg = svg.append("linearGradient")
.attr("id", gradient.id)
.attr("x1", '0%')
.attr("y1", '0%')
.attr("x2", '0%')
.attr("y2", '100%')
.selectAll("stop")
.data([0,100])
.join("stop")
.attr("offset", d => `${d}%`)
.attr("stop-color", d=> colors(d));
}
let label;
if (showSubtitles) {
svg
.selectAll("place")
.data(places.features)
.enter()
.append("circle")
.attr("class", "place")
.attr("r", 2.5)
.attr("transform", function(d) {
return "translate(" + projection(d.geometry.coordinates) + ")";
});

label = svg
.selectAll(".place-label")
.data(places.features)
.enter()
.append("text")
.attr("class", "place-label")
.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("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 => {
return " (" + currentData.find(dd => dd.city === d.properties.name)[confirmed_or_deaths] + ")";
});
}

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

// return Object.assign(wrapper, {
// update(i) {
// const t = svg
// .transition()
// .duration(i === 0 ? 0 : delay)
// .ease(d3.easeLinear);
// if (showSubtitles) {
// label.select("tspan")
// .text(d => " (" + currentData.find(dd => dd.city === d.properties.name)[confirmed_or_deaths] + ")");
// }

// if (scale === "bolhas") {
// bubble
// .data(currentData)
// .call(b => {
// b.transition(t)
// .attr("fill", d => colorScale(d[confirmed_or_deaths]))
// .attr("r", d => radius(d[confirmed_or_deaths]));
// })
// .select("title")
// .text(
// d =>
// `${d.city}: ${numFormat(d[confirmed_or_deaths])}`
// );
// } else {
// espinho
// .data(currentData)
// .call(b => {
// b.transition(t)
// .attr("points", d => {
// const _d = currentData.find(dd => dd.city_ibge_code === d.city_ibge_code);
// const h = (_d !== undefined)? yScale(_d[confirmed_or_deaths]) : 0;
// const projectionxy = projection([d.longitude, d.latitude]);
// const x = projectionxy[0];
// const y = projectionxy[1];
// return `${x - 4},${y} ${x},${y - h} ${x + 4},${y}`
// }).attr("display", d => d[confirmed_or_deaths] === 0 ? "none" : "inline");
// })
// .select("title")
// .text(
// d =>
// `${d.city}: ${numFormat(+d[confirmed_or_deaths])} casos`
// );
// }
// }
// });
}
Insert cell
Insert cell
legendRadii = [maxCases / 8, maxCases / 4, maxCases / 2, maxCases].map(d=>Math.round(d))
Insert cell
currentData = data[Object.keys(data)[Object.keys(data).length -1 - index]];
Insert cell
draw = {
map.update(index);
}
Insert cell
w = Math.min(width, 700)
Insert cell
h = 500
Insert cell
Insert cell
Insert cell
Insert cell
indexSetter = {
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 = 250
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
data = {
Object.keys(data_csv).forEach( key => {
data_csv[key] = data_csv[key].map(d => {
let value = data_city.find(e => d.z === e.city_ibge_code);
return { ...d, ...value }
})
});
return data_csv;
}
Insert cell
data_csv = d3.nest().key(d => d.date).object(await d3.csvParse(await FileAttachment("br_ndays.csv").text(), d => {
d["z"] = +d["z"];
d["c"] = +d["c"];
d["d"] = +d["d"];
return d;
}))
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
path = d3.geoPath().projection(projection)
Insert cell
showSubtitles = w > 600;
Insert cell
projection = d3.geoMercator()
.fitExtent([[0, 0], [showSubtitles ? (w - 50) : w, h]], provinces);
Insert cell
topCities = [...recentData].sort((a,b) => b[confirmed_or_deaths] - a[confirmed_or_deaths]).slice(0,5);
Insert cell
places = ({
type: "FeatureCollection",
features: [
{
type: "Feature",
properties: { name: "Curitiba" },
geometry: { type: "Point", coordinates: [-49.2646, -25.4195 ] }
},
{
type: "Feature",
properties: { name: "São Paulo" },
geometry: { type: "Point", coordinates: [-46.6395, -23.5329] }
},
// {
// type: "Feature",
// properties: { name: "Rio de Janeiro" },
// geometry: { type: "Point", coordinates: [-43.2003, -22.9129] }
// },
{
type: "Feature",
properties: { name: "Fortaleza" },
geometry: { type: "Point", coordinates: [-38.5423, -3.71664] }
},
{
type: "Feature",
properties: { name: "Manaus" },
geometry: { type: "Point", coordinates: [-60.0212, -3.11866] }
},
{
type: "Feature",
properties: { name: "Brasília" },
geometry: { type: "Point", coordinates: [-47.9297, -15.7795] }
},
{
type: "Feature",
properties: { name: "Recife" },
geometry: { type: "Point", coordinates: [-34.8771, -8.04666] }
},
{
type: "Feature",
properties: { name: "Salvador" },
geometry: { type: "Point", coordinates: [-38.5011, -12.9718] }
},
{
type: "Feature",
properties: { name: "Porto Alegre" },
geometry: { type: "Point", coordinates: [-51.2065, -30.0318] }
},
{
type: "Feature",
properties: { name: "Belo Horizonte" },
geometry: { type: "Point", coordinates: [-43.9266, -19.9102] }
},
]
})
Insert cell
Insert cell
Insert cell
Insert cell
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