Javascript 使文本适合 SVG 元素(使用 D3/JS)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/11007640/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Fit Text into SVG Element (Using D3/JS)
提问by mike
I want to write text inside a rectangle I create as follows:
我想在我创建的矩形内写入文本,如下所示:
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')?
However, as you can see (http://jsfiddle.net/Tmj7g/3/) the text gets cut off. Any nifty ways to write a paragraph inside of the svg rectangle created? Thanks,
但是,正如您所看到的(http://jsfiddle.net/Tmj7g/3/),文本被切断了。在创建的 svg 矩形内写一个段落有什么好方法吗?谢谢,
回答by Lars Kotthoff
The answer to this questionmight be relevant. SVG provides no way of wrapping text automatically, but you can embed HTML within SVGs and then use a div
for example.
这个问题的答案可能是相关的。SVG 不提供自动换行文本的方法,但您可以将 HTML 嵌入到 SVG 中,然后使用div
例如。
I've updated the jsfiddle here, but it doesn't work that well together with the animation. If you want to make it work properly and behave like any other SVG element, you'll have to pre-compute the line breaks and insert them manually.
我在这里更新了 jsfiddle ,但它与动画的配合效果不佳。如果你想让它正常工作并且表现得像任何其他 SVG 元素,你必须预先计算换行符并手动插入它们。
回答by GusOst
To make it work with the animations just enclose in a group element and animate that one instead. http://jsfiddle.net/MJJEc/
要使其与动画一起使用,只需将其包含在一个组元素中并为其设置动画。 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)");
回答by arunkjn
This technique might come in handy. It works with the current svg spec and without foreignObject element http://bl.ocks.org/mbostock/7555321
这种技术可能会派上用场。它适用于当前的 svg 规范并且没有 foreignObject 元素 http://bl.ocks.org/mbostock/7555321
回答by dirk
I had a similar issue and found a reasonable solution by calculating the width of my box. Secondly, I figured out that on average the character width for my current font is about 8. Next I simply do a substring on the text to be displayed. That seems to work perfectly in most cases.
我有一个类似的问题,并通过计算我的盒子的宽度找到了一个合理的解决方案。其次,我发现我当前字体的平均字符宽度大约是 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");
回答by maia
Another approach, when trying to fit a straight line of text into an svg element, could use the strategy found in http://bl.ocks.org/mbostock/1846692:
另一种方法,当尝试将一条直线文本放入 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");