viewof divergentBarChart = {
donorVsRecipient.sort((a, b) => {
const maxA = Math.max(a.donado, a.recibido);
const maxB = Math.max(b.donado, b.recibido);
return maxB - maxA;
});
const width = 800;
const barHeight = 35;
const margin = { top: 30, right: 30, bottom: 30, left: 130 };
const height = donorVsRecipient.length * (barHeight + 10) + margin.top + margin.bottom;
const innerWidth = width - margin.left - margin.right;
const formatMoney = value => {
if (value >= 1000000000) {
return `$${(value / 1000000000).toFixed(1)}B`;
} else if (value >= 1000000) {
return `$${(value / 1000000).toFixed(1)}M`;
} else if (value >= 1000) {
return `$${(value / 1000).toFixed(0)}K`;
} else {
return `$${value}`;
}
};
const maxValue = d3.max(donorVsRecipient, d => Math.max(d.donado, d.recibido));
const xScale = d3.scaleLinear()
.domain([0, maxValue * 1.1])
.range([0, innerWidth / 2 - 20]);
const yScale = d3.scaleBand()
.domain(donorVsRecipient.map(d => d.pais))
.range([margin.top, height - margin.bottom])
.padding(0.2);
const svg = d3.create("svg")
.attr("width", width)
.attr("height", height)
.attr("viewBox", [0, 0, width, height])
.attr("style", "max-width: 100%; height: auto; font-family: Arial, sans-serif;");
svg.append("g")
.selectAll("line")
.data(donorVsRecipient)
.join("line")
.attr("x1", margin.left)
.attr("x2", width - margin.right)
.attr("y1", d => yScale(d.pais) + yScale.bandwidth() / 2)
.attr("y2", d => yScale(d.pais) + yScale.bandwidth() / 2)
.attr("stroke", "#f0f0f0")
.attr("stroke-dasharray", "3,3");
const midPoint = margin.left + innerWidth / 2;
svg.append("g")
.selectAll("rect.donado")
.data(donorVsRecipient)
.join("rect")
.attr("class", "donado")
.attr("x", d => midPoint - xScale(d.donado))
.attr("y", d => yScale(d.pais))
.attr("width", d => xScale(d.donado))
.attr("height", yScale.bandwidth())
.attr("fill", "#4CAF50");
svg.append("g")
.selectAll("rect.recibido")
.data(donorVsRecipient)
.join("rect")
.attr("class", "recibido")
.attr("x", midPoint)
.attr("y", d => yScale(d.pais))
.attr("width", d => xScale(d.recibido))
.attr("height", yScale.bandwidth())
.attr("fill", "#F44336");
svg.append("g")
.attr("text-anchor", "end")
.selectAll("text")
.data(donorVsRecipient)
.join("text")
.attr("x", margin.left - 10)
.attr("y", d => yScale(d.pais) + yScale.bandwidth() / 2)
.attr("dy", "0.35em")
.attr("fill", "#333")
.style("font-size", "14px")
.text(d => d.pais);
svg.append("text")
.attr("x", midPoint - innerWidth / 4)
.attr("y", margin.top / 2)
.attr("text-anchor", "middle")
.attr("fill", "#4CAF50")
.attr("font-weight", "bold")
.style("font-size", "14px")
.text("Donado");
svg.append("text")
.attr("x", midPoint + innerWidth / 4)
.attr("y", margin.top / 2)
.attr("text-anchor", "middle")
.attr("fill", "#F44336")
.attr("font-weight", "bold")
.style("font-size", "14px")
.text("Recibido");
svg.append("g")
.selectAll("text.donado")
.data(donorVsRecipient)
.join("text")
.attr("class", "donado")
.attr("text-anchor", "middle")
.attr("x", d => {
const barWidth = xScale(d.donado);
return barWidth > 60 ? midPoint - barWidth / 2 : null;
})
.attr("y", d => yScale(d.pais) + yScale.bandwidth() / 2)
.attr("dy", "0.35em")
.attr("fill", "white")
.attr("font-weight", "bold")
.style("font-size", "12px")
.text(d => d.donado > 0 ? formatMoney(d.donado) : "");
svg.append("g")
.selectAll("text.recibido")
.data(donorVsRecipient)
.join("text")
.attr("class", "recibido")
.attr("text-anchor", "middle")
.attr("x", d => {
const barWidth = xScale(d.recibido);
return barWidth > 60 ? midPoint + barWidth / 2 : null;
})
.attr("y", d => yScale(d.pais) + yScale.bandwidth() / 2)
.attr("dy", "0.35em")
.attr("fill", "white")
.attr("font-weight", "bold")
.style("font-size", "12px")
.text(d => d.recibido > 0 ? formatMoney(d.recibido) : "");
svg.append("g")
.selectAll("text.donado-outside")
.data(donorVsRecipient.filter(d => xScale(d.donado) <= 60 && d.donado > 0))
.join("text")
.attr("class", "donado-outside")
.attr("text-anchor", "end")
.attr("x", d => midPoint - xScale(d.donado) - 5)
.attr("y", d => yScale(d.pais) + yScale.bandwidth() / 2)
.attr("dy", "0.35em")
.attr("fill", "#4CAF50")
.attr("font-weight", "bold")
.style("font-size", "12px")
.text(d => formatMoney(d.donado));
svg.append("g")
.selectAll("text.recibido-outside")
.data(donorVsRecipient.filter(d => xScale(d.recibido) <= 60 && d.recibido > 0))
.join("text")
.attr("class", "recibido-outside")
.attr("text-anchor", "start")
.attr("x", d => midPoint + xScale(d.recibido) + 5)
.attr("y", d => yScale(d.pais) + yScale.bandwidth() / 2)
.attr("dy", "0.35em")
.attr("fill", "#F44336")
.attr("font-weight", "bold")
.style("font-size", "12px")
.text(d => formatMoney(d.recibido));
return svg.node();
}