如何在d3.js中执行.append循环?

时间:2014-01-23 23:58:44

标签: javascript d3.js

我正在多行中为我的svg绘制文字标签。我的解决方案是工作正常,但它有一个限制,它不会绘制比我硬编码更多的行,并且还有一些低效的处理。有没有更好的方法来实现这一点,而不必每次都重新解析名称字符串,并将tspan附加恰当的次数?

node.append("text")
.attr("id", function(d){ return "contact-node-label-"+d.id })
.style("text-anchor", "middle")
.attr("dy", function(d)
{
    // split name by space and -
    var n = d.name.replace("-","- ").split(" ") // this expression is repeated
    return n.length/3-(n.length-1)*0.9+'em'
})
.text(function(d)
{
    var n = d.name.replace("-","- ").split(" ")
    // return first part of name
    return n[0]
})
// some kind of loop would start here
.append("tspan").attr('x',0).attr('dy','1em').text(function(d)
{
    var n = d.name.replace("-","- ").split(" ");
    if (n.length > 1) return n[1];
})
// second round of loop would be this
.append("tspan").attr('x',0).attr('dy','1em').text(function(d)
{
    var n = d.name.replace("-","- ").split(" ");
    if (n.length > 2) return n[2];
})

也许我可以使用以下代码。问题是在方法内部创建(并重新创建)n,如果我将其保存在外部,则会引用错误的数据。解决方案是能够将此代码放在其中一个方法中,但我无法使其工作(无论是在text方法中,还是在tspan append方法中):

d3.select(this).append("tspan").attr('x',0).attr('dy','1em').text( n[i] )

1 个答案:

答案 0 :(得分:6)

看起来像.each的作业:

node.append("text")
    .each(function(d) {
        // split name by space and -
        var n = d.name.replace("-","- ").split(" ");
        // get the current element
        var text = d3.select(this)
            .attr("dy", n.length / 3 - (n.length-1) * 0.9 + 'em')
            .text(n[0]);
        // now loop
        for (var i = 1; i < n.length; i++) {
            text.append("tspan")
                .attr('x', 0)
                .attr('dy', '1em')
                .text(n[i])
        }
    });

如此处所示,.each的一大优势在于它为您提供了每个元素的工作范围,从而可以轻松避免重复计算。