在圈内包裹文字

时间:2014-01-03 22:27:59

标签: javascript text svg d3.js geometry

我正在使用d3绘制UML图,并希望将文本包装在用d3绘制的形状中。我已经得到了下面的代码,无法找到解决方案,使文本“适合”我的形状(见下图)。

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

4 个答案:

答案 0 :(得分:7)

SVG不提供文本换行,但使用foreignObject可以实现类似的效果。假设radius是圆的半径,我们可以计算适合圆圈的框的尺寸:

var side = 2 * radius * Math.cos(Math.PI / 4),
    dx = radius - side / 2;

var g = svg.append('g')
    .attr('transform', 'translate(' + [dx, dx] + ')');

g.append("foreignObject")
    .attr("width", side)
    .attr("height", side)
    .append("xhtml:body")
    .html("Lorem ipsum dolor sit amet, ...");

小组应该少量移位以使文本居中。我知道这不是所要求的,但它可能会有所帮助。我写了一个小fiddle。结果将如下所示:

enter image description here

答案 1 :(得分:4)

这是我能做的最好的事情。

enter image description here

我希望居中文本放在SVG中的圆圈或矩形内。 无论文本长度如何,文本都应保持居中(水平/垂直)。



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>
&#13;
&#13;
&#13;

transform属性不是必需的,我使用translate(-r,-r),以便foreignObject的(x,y)类似于SVG圈的(cx,cy),并且宽度,高度= 2 * r,r为半径。

我这样做是用作D3力布局中的节点。我将这个片段翻译成javascript D3的风格。

答案 2 :(得分:4)

如果您将内容添加到SVG形状正下方的<text>元素内,则可以使用D3plus&#39; .textwrap()功能就是这样做的。我引用了documentation

  

使用d3plus.textwrap,SVG <text>元素可以分开   <tspan>行,就像HTML与<div>元素一样....   D3plus会自动检测是否有<rect><circle>元素   直接放在DOM中的<text>容器元素之前,并使用   用于包装文本的元素的形状和尺寸。如果它找不到   一个,或者该行为需要被覆盖,他们可以手动   使用.shape( ).width( ).height( )指定。

我已经创建了一个codepen来更好地说明这一点,因为文档中的示例可能有点令人困惑:http://codepen.io/thdoan/pen/rOPYxE

答案 3 :(得分:1)

这不太理想,但是@ Pablo.Navarro的回答让我得到了以下结论。

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

var radius = 60,
    x      = 150,
    y      = 100,
    side   = 2 * radius * Math.cos(Math.PI / 4),
    dx     = radius - side / 2;

var global = svg.append('g')
  .attr('transform', 'translate(' + [ dx, dx ] + ')');

global.append('circle')
  .attr('cx', x)
  .attr('cy', y)
  .attr('r', radius);

global.append('foreignObject')
  .attr('x', x - (side/2))
  .attr('y', y - (side/2))
  .attr('width', side)
  .attr('height', side)
  .attr('color', 'red')
  .append('xhtml:p')
    .text('Text meant to fit within circle')
    .attr('style', 'text-align:center;padding:2px;margin:2px;');

结果

result