gpt4 book ai didi

d3.js - 如何更改 d3 图例条目间距/对齐方式

转载 作者:行者123 更新时间:2023-12-01 10:43:17 24 4
gpt4 key购买 nike

我有这个传说:

enter image description here

如您所见,每个图例条目的宽度相同。相反,我希望每个图例条目的宽度根据条目符号和文本的宽度而变化。最终,我希望前导条目文本的结尾与下一个条目符号的开头之间的距离相同。换句话说,我希望“OA”和加号之间的距离与“OI”和菱形以及“RARC”和正方形之间的距离相同。我需要它基于像素(字符串长度不够)。我一直在尝试各种各样的东西,但都没有成功。

这是我的代码:

        var legendData = [["OA", "yellow", "circle"], ["OI", "blue", "cross"], ["RARC", "green", "diamond"], ["CAPE", "red", "square"], ["Other", "black", "triangle-down"]];

this.svg.selectAll('.legend').remove() //remove remnants of previous legend so new legend has clean slate...eliminates overlays during resizing

var legend = this.svg.append('g')
.attr("class", "legend")
.attr("height", 0)
.attr("width", 0)
.attr('transform', 'translate(' + (ScatterChart.Config.margins.left + (width * .008)) + ',' + (height += .40 * ScatterChart.Config.margins.bottom) + ')');

var legendRect = legend
.selectAll('g')
.data(legendData)
;

var labelLength = 0
var labelLengthPrevious = 0

var legendRectE = legendRect.enter()
.append("g")
.attr("transform", function (d, i) {
//labelLength = labelLengthPrevious //Need to figure out pixel lengths
//labelLengthPrevious += (d[0].length) + 50
//return 'translate(' + labelLength + ', ' + 0 + ' )'; // y is constant and x growing
return 'translate(' + (i * (.15 * width)) + ', ' + 0 + ' )'; // y is constant and x growing
})
;

legendRectE
.append('path')
.attr("d", d3.svg.symbol().type((d) => {
return d[2]
}
).size((d3.min([height, width]) * ScatterChart.Config.axisFontMultiplier) * (d3.min([height, width]) * ScatterChart.Config.symbolSizeMultiplier)))
.style("fill", function (d) {
return d[1];
})
.attr('stroke', 'black')
;

//This asserts legendRectE as a node...I think. I do this so I can use the width and height measurements of legendRectE.
var node: SVGElement = <SVGElement>legendRectE.node()

legendRectE
.append("text")
.attr("x", function (d) {
return node.getBoundingClientRect().width
})
.attr("y", function (d) {
return node.getBoundingClientRect().height / 2.25
})
.text(function (d) {
return d[0];
})
.style('font-size', function () { return d3.min([height, width]) * ScatterChart.Config.axisFontMultiplier + "px" })
;

我认为答案与这一行有关: return 'translate(' + (i * (.15 * width)) + ', ' + 0 + ' )'; // y is constant and x growing .现在,它只是通过将索引乘以图表宽度的 15% 向右移动。我想我需要以某种方式替换 legendRectE 的宽度(或 legendRectlegend )代替 (I * (.15 * width)) .我不知道该怎么做。

可以看到我用下面的方式得到了 legendRectE的宽度后面的代码: var node: SVGElement = <SVGElement>legendRectE.node() ,其次是 node.getBoundingClientRect().width .
node.getBoundingClientRect().width给我一个宽度值,您现在可以看到它正在使用它,但是当我使用相同的方法来确定我提到的翻译值时,它会窒息;当我使用 legendRectlegend而不是 legendRectE我只得到'0'。

我以为我可以像这样编辑转换函数:
    var legendRectE = legendRect.enter()
.append("g")
.attr("transform", function (d, i) {
var node: SVGElement = <SVGElement>legendRectE.node()
return 'translate(' + node.getBoundingClientRect().width + ', ' + 0 + ' )'; // y is constant and x growing
})
;

显然,我错了。任何想法/建议?

附言我正在使用 d3 v3.5。

最佳答案

挑战在于(据我所知)在最初添加元素时很难确定转换,因为宽度未知。但是您可以在所有图例条目都附加后返回并计算它们的宽度,然后相应地重新定位图例条目。

下面的代码段将所有内容相互重叠以开始,然后计算 svg每个图例的宽度 g使用 getBBox .然后,使用 d3.sum,计算附加在它之前的每个元素的宽度(因此应该在它的左侧)并相应地将转换值设置为这些宽度的总和。

它可能可以清理一点,它有点快。如果在元素被正确定位之前存在滞后,透明地附加它们然后在它们定位后淡入可能是一个优雅的(视觉上,不太那么编程)解决方案(或最初将它们附加到 View 框之外)。

d3v4:

var data = ['short text','much longer text','the longest text passage','short text'];

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

var groups = svg.selectAll('g')
.data(data)
.enter()
.append('g');

var rect = groups.append('rect')
.attr('fill',function(d,i) { return d3.schemeCategory10[i];})
.attr('height',30)
.attr('width',30);

var text = groups.append('text')
.attr('y', 20)
.attr('x', 35)
.text(function(d) { return d; });

// Now space the groups out after they have been appended:
var padding = 10;
groups.attr('transform', function(d,i) {
return "translate("+(d3.sum(data, function(e,j) {
if (j < i) { return groups.nodes()[j].getBBox().width; } else return 0; }) + padding * i) + ",0)";
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.5.0/d3.min.js"></script>


d3v3:

var data = ['short text','much longer text','the longest text passage','short text'];

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

var groups = svg.selectAll('g')
.data(data)
.enter()
.append('g');

var color = ["orange","red","purple","green"];

var rect = groups.append('rect')
.attr('fill',function(d,i) { return color[i];})
.attr('height',30)
.attr('width',30);

var text = groups.append('text')
.attr('y', 20)
.attr('x', 35)
.text(function(d) { return d; });

// Now space the groups out after they have been appended:
var padding = 10;
groups.attr('transform', function(d,i) {
return "translate("+(d3.sum(data, function(e,j) {
if (j < i) { return groups[0][j].getBBox().width; } else return 0; }) + padding * i) + ",0)";
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>

关于d3.js - 如何更改 d3 图例条目间距/对齐方式,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42790987/

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