Snippets

Adam Labadorf Flexible wordwrap with D3 and coffeescript

Created by Adam Labadorf last modified
svg = d3.select "body"
        .append "svg"
rect = svg.append "rect"
rect.attr "width", 100
    .attr "height", 200
    .style "fill", "#eef"
text = svg.append "text"
text.attr "x", 2
    .attr "y", 2
    .style "dominant-baseline", "text-before-edge"
    .text "some long text so I can try out laying elements vertically that require word wrapping"
    .wordwrap 96 # wrap to 96 px
wordwrap = (width) ->
  this.each () ->
    text = d3.select this
    words = text.text().split(/\s+/).reverse()
    line = []
    line_height = text.node().getBBox().height
    # can get the actual font height, but on chrome it seems like getBBox().height
    # is more accurate
    #line_height = parseInt window.getComputedStyle(this).fontSize, 10
    tspan = text.text null
      .append "tspan"

    while words.length > 0 
      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 "dy", line_height + "px"
          .attr "dx", -tspan.node().getComputedTextLength() + "px"
          .text word
d3.selection.prototype.wordwrap = wordwrap

Comments (0)