Skip to content

Commit fb20928

Browse files
committed
bar chart margin fix
1 parent e7a4ee1 commit fb20928

1 file changed

Lines changed: 83 additions & 8 deletions

File tree

js/script.js

Lines changed: 83 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -812,6 +812,52 @@ document.addEventListener("DOMContentLoaded", function () {
812812
.text(title);
813813
}
814814

815+
function wrapSvgText(textSelection, maxWidth) {
816+
textSelection.each(function () {
817+
const text = d3.select(this);
818+
const originalText = text.text();
819+
820+
const words = originalText
821+
.replace(/\s+·\s+/g, " · ")
822+
.split(/\s+/)
823+
.reverse();
824+
825+
let word;
826+
let line = [];
827+
let lineNumber = 0;
828+
829+
const lineHeight = 1.1;
830+
const x = text.attr("x");
831+
const y = text.attr("y");
832+
const dy = parseFloat(text.attr("dy") || 0);
833+
834+
text.text(null);
835+
836+
let tspan = text.append("tspan")
837+
.attr("x", x)
838+
.attr("y", y)
839+
.attr("dy", `${dy}em`);
840+
841+
while ((word = words.pop())) {
842+
line.push(word);
843+
tspan.text(line.join(" "));
844+
845+
if (tspan.node().getComputedTextLength() > maxWidth && line.length > 1) {
846+
line.pop();
847+
tspan.text(line.join(" "));
848+
849+
line = [word];
850+
851+
tspan = text.append("tspan")
852+
.attr("x", x)
853+
.attr("y", y)
854+
.attr("dy", `${++lineNumber * lineHeight + dy}em`)
855+
.text(word);
856+
}
857+
}
858+
});
859+
}
860+
815861
function renderChangeBars(data, indicator, endYear) {
816862
const container = d3.select("#change-chart");
817863
if (container.empty()) return;
@@ -893,10 +939,14 @@ document.addEventListener("DOMContentLoaded", function () {
893939
})
894940
);
895941

896-
svg.append("g")
942+
const yAxis = svg.append("g")
897943
.attr("transform", `translate(${margin.left},0)`)
898944
.call(d3.axisLeft(y));
899945

946+
yAxis.selectAll(".tick text")
947+
.attr("font-size", 12)
948+
.call(wrapSvgText, margin.left - 24);
949+
900950
svg.selectAll("rect.bar")
901951
.data(rows)
902952
.enter()
@@ -915,21 +965,46 @@ document.addEventListener("DOMContentLoaded", function () {
915965
.append("text")
916966
.attr("class", "value")
917967
.attr("x", (d) => {
918-
const offset = d.delta >= 0 ? 8 : -8;
919-
const rawX = x(d.delta) + offset;
920-
return Math.max(margin.left + 6, Math.min(width - margin.right - 6, rawX));
968+
const zeroX = x(0);
969+
const endX = x(d.delta);
970+
971+
const outsideOffset = d.delta >= 0 ? 8 : -8;
972+
973+
// Normal outside-label position
974+
let labelX = endX + outsideOffset;
975+
976+
// If a negative label would crash into the y-axis labels,
977+
// move it inside the bar near the zero line instead.
978+
if (d.delta < 0 && labelX < margin.left + 50) {
979+
labelX = endX + 50;
980+
}
981+
982+
// If a positive label would fly off the right edge, pull it inside.
983+
if (d.delta > 0 && labelX > width - margin.right - 12) {
984+
labelX = width - margin.right - 12;
985+
}
986+
987+
return labelX;
921988
})
922989
.attr("y", (d) => y(d.category) + y.bandwidth() / 2 + 4)
923990
.attr("text-anchor", (d) => {
924-
const offset = d.delta >= 0 ? 8 : -8;
925-
const rawX = x(d.delta) + offset;
991+
const zeroX = x(0);
992+
const endX = x(d.delta);
926993

927-
if (rawX > width - margin.right - 6) return "end";
928-
if (rawX < margin.left + 6) return "start";
994+
let labelX = endX + (d.delta >= 0 ? 8 : -8);
995+
996+
if (d.delta < 0 && labelX < margin.left + 12) {
997+
return "end";
998+
}
999+
1000+
if (d.delta > 0 && labelX > width - margin.right - 12) {
1001+
return "end";
1002+
}
9291003

9301004
return d.delta >= 0 ? "start" : "end";
9311005
})
9321006
.attr("font-size", 12)
1007+
.attr("font-weight", 600)
9331008
.attr("fill", "#333")
9341009
.text((d) => formatValue(d.delta));
9351010

0 commit comments

Comments
 (0)