Skip to content

Instantly share code, notes, and snippets.

@mationai
Created November 16, 2021 21:57
Show Gist options
  • Save mationai/30d3ba7de34ad4f1effed0123f1ffdcb to your computer and use it in GitHub Desktop.
Save mationai/30d3ba7de34ad4f1effed0123f1ffdcb to your computer and use it in GitHub Desktop.
svg text wrap within d3
d3.selection.prototype.textwrap = function(spec){
d3.addTspans(this, this.text(), spec);
return this;
}
d3.addTspans = function(textElm, text, spec){
var tspans = textElm.selectAll('tspan');
if (tspans.notNull() && text==textElm.datum().txt){
return tspans[0].map(function(tspan){
return d3.select(tspan);
});
}
var
words = text.split(/\s+/) // split on whitespace
,word = words.shift()
,computedLen
,line = []
,lineStr
,x = spec.x || textElm.attr('x') || 0
,y = spec.y || textElm.attr('y') || 0
,tspan = textElm.appendTspan(x, y)
,tspans = [tspan] // init tspans to [empty tspan]
,lineNum = 0
,vAlign = spec.vAlign
,maxLinesReached = false
,maxWd = spec.width
,isGroup = spec.isGroup
,isObject = spec.isObject
,dots
;
if (word==='')
word = words.shift();
while (word){
// push next word to line
line.push(word);
lineStr = line.join(' ');
tspan.text(lineStr);
if (tspan.node().getComputedTextLength() > maxWd){
// word overflowed tspan, remove it from line
line.pop();
lineStr = line.join(' ');
maxLinesReached = tspans.length >= spec.maxLines;
dots = maxLinesReached? '...': '';
if (lineStr){
// reset tspan.text to line without the overflowed word
tspan.text(lineStr + dots);
if (maxLinesReached)
break;
else {
// create new tspan with overflowed word
tspan = textElm.appendTspan(x, y, ++lineNum).text(word);
tspans.push(tspan);
}
}
// else line without overflowed word is empty, so
// tspan.text is just the overflowed word
// Either way, tspan.text is the overflowed word now, set line accordingly
line = [word];
computedLen = tspan.node().getComputedTextLength();
if (computedLen > maxWd){
// word > maxWd, reset tspan.text to word trimmed
dots = isObject? '...': '';
tspan.text( word.slice(0,(maxWd/computedLen)*word.length) + dots);
if (words.length && tspans.length < spec.maxLines){
// create empty tspan for next iteration
tspan = textElm.appendTspan(x, y, ++lineNum);
tspans.push(tspan);
line = [];
}
}
}
word = words.shift();
}
// vertical alignment - adjust dy (horizontal alignment via text-anchor)
if (tspans.length > 1 && ['center','middle','bottom'].indexOf(vAlign) != -1){
tspans.forEach(function(tspan){
tspan.attr('dy',
(+tspan.attr('dy').split('em')[0] + h.tspanDy(tspans.length, vAlign))+'em');
});
}
return tspans;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment