Public
Edited
Mar 11
1 fork
3 stars
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
async function createPresidentChart_yearly(data, visibility) {
const svg = d3
.create("svg")
.attr("width", width)
.attr("height", height)
.attr("id", "decretometro-presidents");

// Number of pags
const n = Math.floor(data.perYear);

// Number of columns
const numberColumns = 5;
const nPerColumn = Math.ceil(n / numberColumns);
const resto = n % numberColumns;
const columnsToAdjust = resto ? numberColumns - resto : 0;

// BCKG color
const bckgGroup = svg.append("g").attr("id", "bckgGroup");
bckgGroup
.append("rect")
.attr("width", width)
.attr("height", height)
.style("fill", primaryColor);

// PAPERS
const papersGroup = svg.append("g").attr("id", "papersGroup");
const horizOffset = 47;
const landscapeGroup = papersGroup
.selectAll("g")
.data(d3.range(numberColumns))
.join("g")
.attr("data-column", (d) => d)
.style(
"transform",
(d, i) => `translate(${horizOffset + d * 40}px, ${Math.random() * 10}px)`
);

// Number of documents per column to paint
const itemsColum = nPerColumn;
const columnGroup = landscapeGroup
.selectAll("g")
.data(d3.range(itemsColum))
.join("g")
.style("transform", (d, i) => `translate(${0}px, ${-100}px)`);

// Easiest way: hide one element on resto ones
if (resto) {
const lastColumns = landscapeGroup
.filter((d, i) => i >= resto)
.attr("data-adjust", true)
.select("g")
.style("opacity", 0);
}

columnGroup
.append("rect")
.attr("x", (d, i) => Math.random() * 3)
.attr("y", (d, i) => Math.random() * 3)
.attr("width", docWidth * 0.7)
.attr("height", docHeight * 0.7)
.style("stroke", "grey")
.style("fill", "white")
.attr("transform", `scale(1, .7) rotate(${docAngle})`);

// LEGEND
const textGroup = svg
.append("g")
.attr("id", "textGroup")
.style("fill", "white")
.style("text-anchor", "middle");

// First line: counter
const textCounter = textGroup
.append("text")
.attr("x", width / 2)
.attr("y", height - 70);

const dynamicText = textCounter
.append("tspan")
.text(n)
.style("font-size", "2.2rem");
textCounter.append("tspan").attr("dx", 5).text(`páginas/año`);

// Second line: president name
const presidentLabel = textGroup
.append("text")
.attr("x", width / 2)
.attr("y", height - 40)
.text(data.label)
.style("font-size", "1.2rem");

// IMAGE
const scaleFactor = 0.55;
const widthImg = 306 * scaleFactor;
const heightImg = 166 * scaleFactor;
const imgGroup = svg.append("g").attr("id", "imgGroup");
const img = imgGroup
.append("image")
.attr("width", widthImg)
.attr("height", heightImg)
.attr("x", width / 2 - widthImg / 2 + 10)
.attr("y", -100)
.style("opacity", 0.9)
.attr("class", data.name);

// Pick a different image on each case
imgGroup
.select(".Aznar")
.attr("href", await FileAttachment("aznar-02.png").url());
imgGroup
.select(".Zapatero")
.attr("href", await FileAttachment("zapatero-02.png").url());
imgGroup
.select(".Rajoy")
.attr("href", await FileAttachment("rajoy-02.png").url());
imgGroup
.select(".Sanchez")
.attr("href", await FileAttachment("sanchez-02.png").url());

// ANIMATION - waiting visibility
// "For reusable code, pass the visibility function across cells"
visibility().then(function () {
// The chart is launched after becoming visible, but we need a small delay.
const initialDelay = 800;

// 1. Papers animation
const columnFactorDelay = 300;
columnGroup
.transition()
.duration(300)
//.delay((d, i) => i * 25)
.delay(function (d, i) {
const columnId = d3.select(this.parentNode).attr("data-column");
return columnFactorDelay * columnId + i * 25;
})
.style("transform", (d, i) => `translate(${0}px, ${scaleYYear(i)}px)`);

// 2. Text animation
// https://observablehq.com/@d3/transition-texttween
// Is one column total timespan plus the offset of the other columns
const totalDuration = nPerColumn * 25 + columnFactorDelay * numberColumns;
dynamicText
.transition()
.duration(totalDuration + 200)
.textTween(() => (t) => `${d3.format(",.0f")(d3.interpolate(0, n)(t))}`);

// 3. Image animation
img
.transition()
.duration(500)
.delay(totalDuration)
.attr("y", scaleYYear(nPerColumn) - heightImg + 5);
});

return svg.node();
}
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
RDLPresidentsData = [
{
name: "Aznar",
perMonth: 5.23,
perYear: 63.60,
label: "Aznar (1996-2004)",
politicalParty: "PP"
},
{
name: "Zapatero",
perMonth: 9.49,
perYear: 115.46,
label: "Zapatero (2004-2011)",
politicalParty: "PSOE"
},
{
name: "Rajoy",
perMonth: 27.31,
perYear: 332.30,
label: "Rajoy (2011-2018)",
politicalParty: "PP"
},
{
name: "Sanchez",
perMonth: 72.79,
perYear: 918,
label: "Sánchez (2018-junio 2022)",
politicalParty: "PSOE"
}
]
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
Insert cell
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