我有一个内部有一个矩形的SVG组,并希望矩形作为该组的边界......
<g>
<rect></rect>
</g>
但该群体是动态的,其内容会发生变化。我试图在我的更新功能中调整rect的大小
.attr("x", function(d) { return this.parentNode.getBBox().x })
.attr("y", function(d) { return this.parentNode.getBBox().y })
.attr("width", function(d) { return this.parentNode.getBBox().width })
.attr("height", function(d) { return this.parentNode.getBBox().height })
但似乎发生的事情是,它扩展得相对较好,但是由于组的边界框宽度现在与扩展的rect的宽度相同,因此无法正常缩小(rect&#39; s width是组的宽度,但组的宽度现在是rect的宽度。
有没有办法让SVG组内的矩形正确调整大小并充当边框?
答案 0 :(得分:6)
解决这个问题的方法不止一种。
使用outline
媒体资源( 2014-08-05状态:适用于Chrome和Opera)
<svg xmlns="http://www.w3.org/2000/svg" width="500px" height="500px">
<g style="outline: thick solid black; outline-offset: 10px;">
<circle cx="50" cy="60" r="20" fill="yellow"/>
<rect x="80" y="80" width="200" height="100" fill="blue"/>
</g>
</svg>
请参阅live example。
使用filter
生成边框( 2014-08-05状态:适用于Firefox,但Chrome / Opera在feMorphology上有bug,但应该可以通过使用其他过滤器原语来解决这个问题。)
<svg xmlns="http://www.w3.org/2000/svg" width="100%" height="100%">
<defs>
<filter id="border" x="-5%" y="-5%" width="110%" height="110%">
<feFlood flood-color="black" result="outer"/>
<feMorphology operator="erode" radius="2" in="outer" result="inner"/>
<feComposite in="inner" in2="outer" operator="xor"/>
<feComposite in2="SourceGraphic"/>
</filter>
</defs>
<g filter="url(#border)">
<circle cx="50" cy="60" r="20" fill="yellow"/>
<rect x="80" y="80" width="200" height="100" fill="blue"/>
</g>
</svg>
请参阅live example。
以上两者都会自动更新为该组的大小,而无需修改DOM。
答案 1 :(得分:4)
是的,您可以通过选择组中不是边界矩形的所有子元素,然后根据子项的各个边界框计算整个边界框来找到新的边界框。
假设您的边界矩阵有bounding-rect
类,您可以执行以下操作:
function updateRect() {
// SELECT ALL CHILD NODES EXCEPT THE BOUNDING RECT
var allChildNodes = theGroup.selectAll(':not(.bounding-rect)')[0]
// `x` AND `y` ARE SIMPLY THE MIN VALUES OF ALL CHILD BBOXES
var x = d3.min(allChildNodes, function(d) {return d.getBBox().x;}),
y = d3.min(allChildNodes, function(d) {return d.getBBox().y;}),
// WIDTH AND HEIGHT REQUIRE A BIT OF CALCULATION
width = d3.max(allChildNodes, function(d) {
var bb = d.getBBox();
return (bb.x + bb.width) - x;
}),
height = d3.max(allChildNodes, function(d) {
var bb = d.getBBox();
return (bb.y + bb.height) - y;
});
// UPDATE THE ATTRS FOR THE RECT
svg.select('.bounding-rect')
.attr('x', x)
.attr('y', y)
.attr('width', width)
.attr('height', height);
}
这会将整个边界框的x和y值设置为子节点边界框中的最小x和y值。然后通过找到最大右边界bb.x + bb.width
并减去整个框的x来计算总宽度。然后以与宽度相同的方式计算总高度。
HERE就是一个例子。
答案 2 :(得分:1)
最简单,跨浏览器兼容的方法是实现边框就像我一样使用rect
,但将它放在组外(因为它仍然被边界框定位,它将@Duopixel在评论中提到正确的宽度,高度,x和y。