gpt4 book ai didi

javascript - D3.js 在绘制后更改容器的宽度

转载 作者:行者123 更新时间:2023-11-29 10:59:21 24 4
gpt4 key购买 nike

我有一个看似简单的 d3.js 问题。我正在从一组 json 数据创建一棵树。树由标签组成,标签由环绕一些文本的矩形容器组成。我想根据文本的长度更改矩形的宽度。我知道我应该做类似 this one 的事情,但我很难理解如何做到这一点。

这是我的 JS 代码(去掉了大部分不必要的装饰):

var rectW = 140, rectH = 40;

// Declare the nodes.
var node = draw.selectAll('g.node')
.data(nodes, function(d) { return d.id; });

// Enter the nodes.
var nodeLabel = node.enter().append('g')
.attr('transform', function(d) { return 'translate(' + source.x0 + ',' + source.y0 + ')'; });

var nodeRect = nodeLabel.append('rect')
.attr('width', rectW)
.attr('height', rectH);

var nodeText = nodeLabel.append('text')
.attr('x', rectW / 2)
.attr('y', rectH / 2)
.text(function (d) { return d.name; });

如您所见,我创建了一个 SVG 组,我将容器矩形和包含的文本附加到该组。现在,我想检索每个文本元素的长度,并用它来更改相应矩形元素的宽度。我怎样才能做到这一点?我尝试了我能想到的所有可能的 D3 指令组合,但我对库的了解还不足以满足我的目的。

更新感谢Geraldo Furtado's回答,我设法通过添加以下内容解决了这个问题:

// This arranges the width of the rectangles
nodeRect.attr("width", function() {
return this.nextSibling.getComputedTextLength() + 20;
})
// This repositions texts to be at the center of the rectangle
nodeText.attr('x', function() {
return (this.getComputedTextLength() + 20) /2;
})

最佳答案

这是您的节点的当前结构:

<g>
<rect></rect>
<text></text>
</g>

既然如此,文本就是nextSibling s 的矩形。因此,获取文本长度所需要做的就是使用 nextSibling在矩形选择中:

nodeRect.attr("width", function() {
return this.nextSibling.getComputedTextLength() + rectW
})

我在这里添加 rectW在左侧和右侧保持相同的填充,因为您将文本从 rectW / 2 开始.

如果你不确定文本和矩形之间的关系(谁是第一个 child ,谁是最后一个 child ......),你可以上去,选择组元素,然后选择其中的文本:

nodeRect.attr("width", function() {
return d3.select(this.parentNode).select("text").node().getComputedTextLength() + rectW
})

这是一个基本的演示:

var data = [{
name: "some text",
x: 10,
y: 10
},
{
name: "A very very very long text here",
x: 100,
y: 50
},
{
name: "Another text, this time longer than the previous one",
x: 25,
y: 100
},
{
name: "some short text here",
x: 220,
y: 150
}
];

var svg = d3.select("svg");

var rectW = 140,
rectH = 30;

var node = svg.selectAll(null)
.data(data);

var nodeLabel = node.enter().append('g')
.attr('transform', function(d) {
return 'translate(' + d.x + ',' + d.y + ')';
});

var nodeRect = nodeLabel.append('rect')
.attr('width', rectW)
.attr('height', rectH)
.style("fill", "none")
.style("stroke", "gray")

var nodeText = nodeLabel.append('text')
.attr('x', rectW / 2)
.attr('y', rectH / 2)
.style("dominant-baseline", "central")
.text(function(d) {
return d.name;
});

nodeRect.attr("width", function() {
return this.nextSibling.getComputedTextLength() + rectW
})
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg width="500" height="300"></svg>

为了存储计算出的宽度并在以后使用它,您可以设置另一个属性。例如:

nodeRect.attr("width", function(d) {
return d.rectWidth = this.nextSibling.getComputedTextLength() + rectW
});

这里是demo,看控制台:

var data = [{
name: "some text",
x: 10,
y: 10
},
{
name: "A very very very long text here",
x: 100,
y: 50
},
{
name: "Another text, this time longer than the previous one",
x: 25,
y: 100
},
{
name: "some short text here",
x: 220,
y: 150
}
];

var svg = d3.select("svg");

var rectW = 140,
rectH = 30;

var node = svg.selectAll(null)
.data(data);

var nodeLabel = node.enter().append('g')
.attr('transform', function(d) {
return 'translate(' + d.x + ',' + d.y + ')';
});

var nodeRect = nodeLabel.append('rect')
.attr('width', rectW)
.attr('height', rectH)
.style("fill", "none")
.style("stroke", "gray")

var nodeText = nodeLabel.append('text')
.attr('x', rectW / 2)
.attr('y', rectH / 2)
.style("dominant-baseline", "central")
.text(function(d) {
return d.name;
});

nodeRect.attr("width", function(d) {
return d.rectWidth = this.nextSibling.getComputedTextLength() + rectW
});

nodeLabel.each(function(d) {
console.log(d)
})
<script src="https://d3js.org/d3.v5.min.js"></script>
<svg width="500" height="300"></svg>

关于javascript - D3.js 在绘制后更改容器的宽度,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50359800/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com