我如何得到"打电话"执行D3中的每个数据元素?

时间:2017-11-16 18:52:27

标签: javascript d3.js call

使用D3,我试图为myData显示的每个引用实现一个自动换行插件。最后一行的调用函数是。

问题是它只适用于第一个引用。它使所有其他引号不出现。我不确定如何构造调用,而enter()通常会呈现事物。

var quote=svg.selectAll("text.quote").data(myData);
quote.exit().remove()
quote.enter().append("text")
quote
.attr("class","quote")
.attr("x", function (d,i){ return xScale(i);})
.attr("y", function(d){ return yScale(d.y);})
.text(function(d, i){return d.quote;})
.call(d3.util.wrap(125))

1 个答案:

答案 0 :(得分:5)

你想要selection.each()而不是selection.call()。 Selection.call将只调用一次函数,而.each将为每个数据调用它:

  

selection.each(function)<>

     

按顺序为每个选定的元素调用指定的函数,   传递当前数据(d),当前索引(i)和   当前组(节点),将其作为当前DOM元素   (节点[1])。此方法可用于为每个方法调用任意代码   选定的元素......

比较:

  

selection.call(function [,arguments ...])<>

     

只调用指定的函数一次,传入此选择   以及任何可选参数。

API Documentation(v4,但v3中都存在这两种方法))

有关两者的比较,请参阅以下代码段:

var data = [10,20,30,40];

var selection = d3.select("body").selectAll(null)
  .data(data)
  .enter()
  .append("p")
  .each(function(d) {
    console.log("each: " + d); // d is datum
  })
  .call(function(d) {
    console.log("call: ") 
    console.log(d.data()); // d is selection
  })
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/4.10.0/d3.min.js"></script>

要在每个项目上调用此函数一次,您可以在.each中使用.call。我使用g来放置文本,以便此实用程序创建的tspans正确定位(否则它们重叠)。以下代码片段使用您的代码(自动换行实用程序位于顶部,因为我无法快速找到cdn):

d3.util = d3.util || {};

d3.util.wrap = function(_wrapW){ 
    return function(d, i){
        var that = this;

        function tspanify(){ 
            var lineH = this.node().getBBox().height;
            this.text('')
                .selectAll('tspan')
                .data(lineArray)
                .enter().append('tspan')
                .attr({
                    x: 0,
                    y: function(d, i){ return (i + 1) * lineH; } 
                })
                .text(function(d, i){ return d.join(' '); })
        }   

        function checkW(_text){ 
            var textTmp = that
                .style({visibility: 'hidden'})
                .text(_text);
            var textW = textTmp.node().getBBox().width;
            that.style({visibility: 'visible'}).text(text);
            return textW; 
        }

        var text = this.text();
        var parentNode = this.node().parentNode;
        var textSplitted = text.split(' ');
        var lineArray = [[]];
        var count = 0;
        textSplitted.forEach(function(d, i){ 
            if(checkW(lineArray[count].concat(d).join(' '), parentNode) >= _wrapW){
                count++;
                lineArray[count] = [];
            }
            lineArray[count].push(d)
        });

        this.call(tspanify)
    }
};

var wrap = d3.util.wrap(11);

var svg = d3.select("body")
 .append("svg")
 .attr("height",400)
 .attr("width",400);

var myData = ["text 1","text 2","text 3"]

var quote = svg.selectAll("text.quote").data(myData);
quote.enter().append("g")

quote.attr("class","quote")
.attr("transform", function (d,i){ return "translate(20," + (i * 40 + 20) + ")" })
.append("text")
.text(function(d, i){return d})
.each(function() {
  d3.select(this).call(d3.util.wrap(11));
})
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>