(async () => {
const margin = { top: 30, right: 30, bottom: 30, left: 30 };
const width = 900;
const height = 500;
const xScale = d3
.scaleLinear()
.rangeRound([margin.left, width - margin.right]);
const yScale = d3
.scaleBand()
.rangeRound([height - margin.bottom, margin.top]);
const colorScale = d3.scaleOrdinal(d3.schemeTableau10);
const xAxis = (g) =>
g
.attr("transform", `translate(0,${height - margin.bottom})`)
.call(d3.axisBottom(xScale).ticks(width / 80))
.call((g) => g.select(".domain").remove());
const yAxis = (g) =>
g
.attr("transform", `translate(${margin.left},0)`)
.call(d3.axisLeft(yScale).tickSizeOuter(0))
.call((g) => g.select(".domain").remove());
class Tooltip {
constructor() {
this.tooltip = d3
.select("body")
.append("div")
.attr("class", "d3-tip")
.style("position", "absolute")
.style("z-index", "10")
.style("visibility", "hidden");
}
show(event, d) {
const total = d3.sum(d.Estado, (s) => s.Hecho);
this.tooltip
.html(
`<strong>Departamento:</strong> <span style='color:red'>${d.Departamento}</span> <br> <strong>Total:</strong> <span style='color:red'>${total}</span>`
)
.style("top", event.pageY - 10 + "px")
.style("left", event.pageX + 10 + "px")
.style("visibility", "visible");
}
hide() {
this.tooltip.style("visibility", "hidden");
}
}
// Preparar los datos para la visualización
const data = await d3.csv(
"https://docs.google.com/spreadsheets/d/e/2PACX-1vRTWPjGdlmWMWsLs3ltdBkKLmWEIiTB_uHqZCucFFot7tThzyyVMqWPAKkcLaoDSPinuMFPErC5kkDG/pub?output=csv"
);
const processedData = d3.rollups(
data,
(v) => d3.sum(v, (leaf) => +leaf.Hecho),
(d) => d.Departamento,
(d) => d.Estado
);
let graphData = processedData.map(([dep, stats]) => ({
Departamento: dep,
Estado: stats.map(([Estado, Hecho]) => ({ Estado, Hecho }))
}));
// Ajuste las escalas de acuerdo con los datos
xScale.domain([
0,
d3.max(graphData, (d) => d3.sum(d.Departamento, (s) => s.Hecho))
]);
yScale.domain(graphData.map((d) => d.Departamento));
colorScale.domain(data.map((d) => d.Estado));
// Generar el gráfico
const svg = d3.create("svg").attr("viewBox", [0, 0, width, height]);
const tooltip = new Tooltip();
svg
.selectAll("g.Estado")
.data(graphData)
.join("g")
.attr("class", "Estado")
.selectAll("rect")
.data((d) => d.Estado)
.join("rect")
.attr("fill", (d) => colorScale(d.Estado))
.attr("x", (d) => xScale(0))
.attr("y", (d) => yScale(d.dep))
.attr("width", (d) => xScale(d.Hecho))
.attr("height", yScale.bandwidth())
.on("mouseover", (event, d) => tooltip.show(event, d))
.on("mouseout", () => tooltip.hide());
svg.append("g").call(xAxis);
svg.append("g").call(yAxis);
// Generar la leyenda
const legend = svg
.append("g")
.attr("font-family", "sans-serif")
.attr("font-size", 10)
.attr("text-anchor", "end")
.selectAll("g")
.data(colorScale.domain().slice().reverse())
.join("g")
.attr("transform", (d, i) => `translate(-50,${i * 20})`);
legend
.append("rect")
.attr("x", width - 19)
.attr("width", 19)
.attr("height", 19)
.attr("fill", colorScale);
legend
.append("text")
.attr("x", width - 24)
.attr("y", 9.5)
.attr("dy", "0.32em")
.text((d) => d);
return svg.node();
})()