我被困在d3(或一般的JavaScript)中。
我想用d3制作一个传奇。 9项的位置应相互依赖。更具体地说:
这是我的简化数组: var dataset = [" Africa"," Asia"," Caribbean"," Central America"," Europe", "中东","北美","大洋洲","南美"];
在x轴上,我想绘制下一个文本40px进一步(向右),然后最后一个文本标签结束。我的意图是每次都在圆圈之间留出相同的空间。因此,下一个文本始终取决于最后一个国家/地区名称的长度。
我试过了:
.attr("x", function(d, i) {return i * 40 + d[i-1].length + 7;})
但控制台说d [i-1]未定义。
我错过了什么?你会如何解决这个问题?
非常感谢提前!非常感激您的帮忙!
埃娃
更新: 实际上我想要绘制的图例不仅包括文字,还包括小圆圈。
这是数组(硬编码的x_pos为d [2]:var dataset = [ ["非洲","#4B7985",5],["亚洲","#58AB86",55],[&#34 ;加勒比","#63A4B5",100],["中美洲","#818181",165],["欧洲&# 34;,"#E9726C",255],["中东","#E3AC73",310],["北美" ,"#B65856",383],["大洋洲","#287E5C",470],["南美",&# 34;#AC8358",530] ];
如何根据国家/地区名称的长度绘制圆圈并在cirlces之间获得相同的间距?
答案 0 :(得分:4)
您可以绘制文本元素以在画布上获取边界框。然后根据最后一个元素的宽度调整位置:
svg.selectAll("text")
.data(data).enter()
.append("text")
.attr("x", function(d) {
return x_pos;
})
.attr("y", 50)
.style("display", "none")
.text(function(d) { return d; });
svg.selectAll("text")
.style("display", "block")
.attr("x", function(d) {
var c_pos = x_pos;
x_pos = x_pos + this.getBBox().width + distance;
return c_pos;
});
答案 1 :(得分:1)
我就是这样做的。
//This will be your array of legends
var legendItems = []
var legendCount = legendItems.length;
var legendSectionWidth = width / (legendCount+1);
//This will be your "y" value going forward. You can assign anything you want. I have used the following if else case, you should replace it with your logic to calculate y.
var vert = 0;
if(legendPosition == "bottom"){
if(showAxes)
vert = height + legendVerticalPad + containerHeight*0.04;
else
vert = height + legendVerticalPad + containerHeight*0.02;
}
for(var i = 0; i < legendCount; i++){
var text = svg.append('text')
.attr('x', (i+1)*legendSectionWidth)
.attr('y', vert)
.attr('class', 'legend-text '+legendItems[i])
.style('text-anchor', 'middle')
.style('dominant-baseline', 'central')
.text(function() {
return legendItems[i];
});
var len = text[0][0].getComputedTextLength();
// you could use circles here, just change the width n height to rx and x and y to cx and cy// you could use circles here, just change the width n height to rx and x and y to cx and cy`enter code here`
//The value 5 is your choice, i use 5px between my rect and text
svg.append('rect')
.attr('x', (i+1)*legendSectionWidth - len/2 - 5 - legendRectSize)
.attr('y', vert - legendRectSize/2)
.attr('width', legendRectSize)
.attr('height', legendRectSize)
.attr('class', function () { return 'legend '+ legendItems[i];} )
.attr('label', function() {
return legendItems[i];
})
}
以下图像证明了图例(矩形和文本的组合)与每个图例等距,并且位于所提供宽度的中心。有了这个逻辑,无论你需要什么样的传说,所有的都将被放置在彼此相等的位置并显示在屏幕中间
我希望这会有所帮助。
答案 2 :(得分:0)
首先,d
指的是单个绑定数据点,而i
指的是数据集中的索引。要查看以前的数据点,您需要引用原始数据集,而不是提供的数据点。
假设你有:
var dataset = ["Africa","Asia", "Caribbean", "Central America", "Europe", "Middle East", "North America", "Oceania", "South America"];
d3.select('.foo').data(dataset)....
您可能希望将位置处理程序中的d [i - 1]引用更改为数据集[i - 1]
修复后,你的第一个元素仍会爆炸,因为它位于dataset[0]
。在这种情况下,dataset[i - 1]
为dataset[-1]
。
您可以将return语句更改为:
return i ? (i * 40 + dataset[i-1].length + 7) : i;