Created
November 16, 2021 21:57
-
-
Save mationai/30d3ba7de34ad4f1effed0123f1ffdcb to your computer and use it in GitHub Desktop.
svg text wrap within d3
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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