Search code examples
javascripttextsvgd3.jsgeometry

Wrap text within circle


I'm using d3 to draw a UML diagram and would like to wrap text within the shapes drawn with d3. I've gotten as far as the code below and can't find a solution to make the text 'fit' within my shape (see image below).

var svg =  d3.select('#svg')
    .append('svg')
        .attr('width', 500)
        .attr('height', 200);

var global = svg.append('g');

global.append('circle')
      .attr('cx', 150)
      .attr('cy', 100)
      .attr('r', 50);

global.append('text')
  .attr('x', 150)
  .attr('y', 100)
  .attr('height', 'auto')
  .attr('text-anchor', 'middle')
  .text('Text meant to fit within circle')
  .attr('fill', 'red');

result


Solution

  • Here is the best I could do.

    enter image description here

    I want to center and wrap a text inside a circle or rect in SVG. The text should remain centered (horizontal/vertical) whatever the text length.

    svg {
        width: 600px;
        height: 200px;
        background-color: yellow;
    }
    .circle {
        background-color: blue;
        height: 100%;
        border-radius: 100%;
        text-align: center;
        line-height: 200px;
        font-size: 30px;
    }
    .circle span {
        line-height: normal;
        display:inline-block;
        vertical-align: middle;
        color: white;
        text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.8);
    }
    <svg>
        <foreignObject width="200" height="200" x="100" y="100" transform="translate(-100,-100)">
            <div class="circle">
                <span>Here is a</span>
            </div>
        </foreignObject>
    
        <foreignObject width="200" height="200" x="300" y="100" transform="translate(-100,-100)">
            <div class="circle">
                <span>Here is a paragraph</span>
            </div>
        </foreignObject>
    
        <foreignObject width="200" height="200" x="500" y="100" transform="translate(-100,-100)">
            <div class="circle">
                <span>Here is a paragraph that requires word wrap</span>
            </div>
        </foreignObject>
    </svg>

    The transform attribute is not mandatory, I'm using a translate(-r, -r) so that the (x,y) of the foreignObject is like the (cx, cy) of the SVG circle, and width, height = 2*r with r the radius.

    I did this to use as nodes within a D3 force layout. I leave as an exercise to translate this snippet into javascript D3's style.