将文本适配到SVG元素中(使用D3/JS)

13

我想在一个矩形中写入文本,我是这样创建矩形的:

body = d3.select('body')

svg = body.append('svg').attr('height', 600).attr('width', 200)

        rect = svg.append('rect').transition().duration(500).attr('width', 150)
                        .attr('height', 100)
                        .attr('x', 40)
                        .attr('y', 100)
                        .style('fill', 'white')
                        .attr('stroke', 'black')

        text = svg.append('text').text('This is some information about whatever')
                        .attr('x', 50)
                        .attr('y', 150)
                        .attr('fill', 'black')​

然而,正如你所看到的 (http://jsfiddle.net/Tmj7g/3/),文字被截断了。有没有巧妙的方法在创建的 SVG 矩形内部编写段落?谢谢。


这个技巧可能会派上用场。 它适用于当前的SVG规范,并且不需要使用foreignObject元素。 http://bl.ocks.org/mbostock/7555321 - arunkjn
4个回答

16
这个问题的答案可能是相关的。SVG没有提供自动换行文本的方法,但是你可以在SVG中嵌入HTML,然后使用例如div
我已经更新了此处的jsfiddle,但它与动画不太兼容。如果你想让它正常工作并表现得像任何其他SVG元素一样,你需要预先计算出换行并手动插入它们。

这个在IE9上能用吗?如果不能,有什么替代方案吗?我知道这个问题很久以前就已经回答过了。 - Jose
是的,在IE9中它根本不起作用,因为它不支持foreign Objects。在D3.js中有没有将文本包装的替代方法? - Jose
1
这不是一个D3问题,而是SVG问题。如果您不需要花哨的图形,可以简单地生成HTML。如果您需要SVG,则可以使用其tspan元素来包装文本,但这样做不太方便。 - Lars Kotthoff

14

为了使它与动画配合使用,只需将其放入组元素中并对该元素进行动画处理即可。 http://jsfiddle.net/MJJEc/

body = d3.select('body')
svg = body.append('svg')
                    .attr('height', 600)
                    .attr('width', 200);
    var g = svg.append('g').attr("transform" ,"scale(0)");
    rect = g.append('rect')
                    .attr('width', 150)
                    .attr('height', 100)
                    .attr('x', 40)
                    .attr('y', 100)
                    .style('fill', 'none')
                    .attr('stroke', 'black')
    text = g.append('foreignObject')
                    .attr('x', 50)
                    .attr('y', 130)
                    .attr('width', 150)
                    .attr('height', 100)
                    .append("xhtml:body")
                    .html('<div style="width: 150px;">This is some information about whatever</div>')

    g.transition().duration(500).attr("transform" ,"scale(1)");

2

我遇到了类似的问题,通过计算我的框的宽度,找到了一个合理的解决方案。 其次,我发现我的当前字体平均字符宽度约为8个单位。 然后,我只需对要显示的文本进行子字符串处理。 在大多数情况下,这似乎完美地解决了问题。

var rectText = rectangles.append("text")
    .text(function(d) {

        TextBoxLength = timeScale(dateFormat.parse(d.endTime)) - timeScale(dateFormat.parse(d.startTime));
        return d.task.substring(0, Math.floor(TextBoxLength / 8));
    })
    .attr("x", function(d) {
        return (timeScale(dateFormat.parse(d.endTime)) - timeScale(dateFormat.parse(d.startTime))) / 2 + timeScale(dateFormat.parse(d.startTime)) + theSidePad;
    })
    .attr("y", function(d, i) {
        return d.position * theGap + 14 + theTopPad;
    })
    .attr("font-size", 12)
    .attr("text-anchor", "middle")
    .attr("text-height", theBarHeight)
    .attr("fill", "#000000");

2

另一种在尝试将一行直线文本适配到SVG元素中的方法,可以使用在http://bl.ocks.org/mbostock/1846692中找到的策略:

node.append("text")
  .text(function(d) { return d.name; })
  .style("font-size", function(d) { return Math.min(2 * d.r, (2 * d.r - 8) / this.getComputedTextLength() * 24) + "px"; })
  .attr("dy", ".35em");

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接