Skip to content

Instantly share code, notes, and snippets.

@roundrobin
Created August 17, 2013 00:08
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save roundrobin/6254545 to your computer and use it in GitHub Desktop.
Save roundrobin/6254545 to your computer and use it in GitHub Desktop.
Custom text wrapping function d3.js / SVG
wrapTextVariableFont: (selectorForTspans, width, d3Selection, lineHeight = 1.2) =>
tspans = d3Selection.selectAll(selectorForTspans)
lineLength = 0
maxLineFontSize = 0
prev = null
firstInLine = null
tspans.each (d, i) ->
elem = d3.select(this)
fontSize = parseFloat(elem.style('font-size'))
text = elem.text()
# A comma, a dot, etc should stick to the previous text - we won't move it to the next line
specialCharacterAtTheEnd = ['.', ',', ':', '!', '?', '%'].indexOf(text) != -1
elementLength = this.getComputedTextLength()
onlySpaces = ! /\S/.test(text)
continueLine = (onlySpaces || lineLength == 0 || lineLength + elementLength <= width || specialCharacterAtTheEnd)
if text.indexOf('\n') == 0
continueLine = false
if continueLine
lineLength += elementLength
maxLineFontSize = Math.max(maxLineFontSize, fontSize)
else # starting a new line
prev.text(prev.text().replace(/\s*$/, ''))
firstInLine && firstInLine
.attr("x", 0 )
.attr("dy", maxLineFontSize * lineHeight)
firstInLine = elem
elem.text(text.replace(/^\s*/, ''))
lineLength = this.getComputedTextLength()
maxLineFontSize = fontSize
prev = elem
if prev
prev.text(prev.text().replace(/\s*$/, ''))
firstInLine && firstInLine
.attr("x", 0 )
.attr("dy", maxLineFontSize * lineHeight)
return d3Selection
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment