How to wrap text in SVG vertically in D3.js?
From this bl.ocks.org you can use the wrap function with little modification:
function wrap(text, width) {
text.each(function() {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.1, // ems
y = text.attr("y"),
dy = parseFloat(text.attr("dy")),
tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > width) {
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", lineHeight + "em").text(word);
}
}
});
}
here is a working snippet:
let graph = {
"nodes": [{
"description": "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed porta consequat felis, eget varius mi volutpat sit amet. Nullam lobortis vehicula felis, in tempor dui. Sed scelerisque purus ac nisl auctor finibus sit amet nec massa. Duis erat sem, suscipit non molestie vitae, accumsan nec tortor. Nulla sed facilisis ligula, nec interdum elit. Nam tortor lectus, sodales ut nulla ac, feugiat ultrices velit. Vestibulum nec ultricies nisi. Donec leo nibh, fringilla eget pretium nec, condimentum in nulla."
}]
}
let svg = d3.select("body")
.append("svg")
.attr("width", 700)
.attr("height", 800);
let nodes = svg.selectAll("circle")
.data(graph.nodes)
.enter()
.append("circle")
.attr("r", 20)
.attr("cx", function(d) {
return 20;
})
.attr("cy", function(d) {
return 20;
})
.style("fill", "red");
let tip;
nodes.on("click", function(d) {
if (tip) {
tip.remove()
};
tip = svg.append("g")
.attr("id", "tip")
.attr("transform", "translate(" + (d3.event.pageX - 10) + "," + (d3.event.pageY - 35) + ")");
let rect = tip.append("rect")
.style("fill", "white")
.style("stroke", "steelblue");
tip.append("text")
.text(d.description)
.attr("dy", "1em")
.attr("x", 5)
.call(wrap, 300)
let bbox = tip.node().getBBox();
rect.attr("width", bbox.width + 5)
.attr("height", bbox.height + 50)
});
function wrap(text, width) {
text.each(function() {
var text = d3.select(this),
words = text.text().split(/\s+/).reverse(),
word,
line = [],
lineNumber = 0,
lineHeight = 1.1, // ems
y = text.attr("y"),
dy = parseFloat(text.attr("dy")),
tspan = text.text(null).append("tspan").attr("x", 0).attr("y", y).attr("dy", dy + "em");
while (word = words.pop()) {
line.push(word);
tspan.text(line.join(" "));
if (tspan.node().getComputedTextLength() > width) {
line.pop();
tspan.text(line.join(" "));
line = [word];
tspan = text.append("tspan").attr("x", 0).attr("y", y).attr("dy", lineHeight + "em").text(word);
}
}
});
}
<p>
click the node to show description
</p>
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.12.2/d3.js"></script>
Text-Wrapping in D3
You need to use svg:foreignObject
with an HTML div
or similar to make this work. SVG itself won't wrap the text.
Wrapping and vertically centering text using D3.js
I realized I was using the number of lines - 1 instead of just the number of lines. Removing the -1 solved the issue.
if (lineNumber > 0) {
const startDy = -(lineNumber * (lineHeight / 2)); // here was the issue
text
.selectAll("tspan")
.attr("dy", (d, i) => startDy + lineHeight * i + "em");
}
Related Topics
Chrome: Timeouts/Interval Suspended in Background Tabs
React: "This" Is Undefined Inside a Component Function
Why Is It Necessary to Set the Prototype Constructor
Angularjs Routing Without the Hash '#'
JavaScript - Track Mouse Position
Converting an Object to a String
JavaScript - Generating Combinations from N Arrays With M Elements
Black and White Text Based on Background Image with CSS
How to Dynamically Modify <Select> in Materialize CSS Framework
Can You Have a JavaScript Hook Trigger After a Dom Element's Style Object Changes
Repeat Animation Every 3 Seconds
Jquery Equivalent of Yui Stylesheet Utility
Jquery Live Scroll Event on Mobile (Work Around)
Is There a JavaScript Function That Can Pad a String to Get to a Determined Length
How to Group Data with an Angular Filter
How to Set a Cookie for Another Domain