4

我正在研究一个简单的 d3 示例,我使用 d3 在页面上放置一些新的 div、添加属性和添加数据驱动的样式。让我绊倒的部分是当我想使用 d3 使用新数据更新某些样式时。我从下面的 jsFiddle ( http://jsfiddle.net/MzPUg/15/ ) 中粘贴了代码。

在最初创建 div 的步骤中,我使用键函数向元素添加索引,在更新步骤(不起作用的部分)中,我还使用键函数。但是从 d3 文档中不清楚的是实际数据连接是如何工作的(例如,索引存储在 DOM 元素中的什么位置?如果有重复的索引怎么办?等等)。

所以,我的知识存在明显的差距,但是在这里保持简单,任何人都可以解释为什么这个例子不起作用?任何有关 d3 中数据连接的精确性质的额外信息都将是锦上添花。(我已经看过http://bost.ocks.org/mike/join/。)

//add a container div to the body and add a class
var thediv = d3.select("body").append("div").attr("class","bluediv");

//add six medium-sized divs to the container div
//note that a key index function is provided to the data method here
//where do the resulting index value get stored?
var mediumdivs = thediv.selectAll("div")
    .data([10,50,90,130,170,210],function(d){return d})
    .enter().append("div")
    .style("top",function(d){return d + "px"})
    .style("left",function(d){return d + "px"})
    .attr("class","meddiv")

//UPDATE STEP - NOT WORKING
//Attempt to update the position of two divs
var newdata = [{newval:30,oldval:10},{newval:80,oldval:50}]        
var mediumUpdate = mediumdivs.data(newdata,function(d){return d.oldval})
    .style("left",function(d){return d.newval + "px"})
4

3 回答 3

1

据我所知,您不会更新已经存在的元素。相反,您告诉 D3 要绘制哪些元素,它会确定要在屏幕上删除或更新的内容。

我用工作代码更新了你的JSFiddle 。我还添加了下面的代码。

//add a container div to the body and add a class
var thediv = d3.select("body").append("div").attr("class", "bluediv");

function update(data) {
    var mediumdivs = thediv.selectAll("div").data(data, function(d) {
        return d;
    });

    // Tell D3 to add a div for each data point.
    mediumdivs.enter().append("div").style("top", function(d) {
        return d + "px";
    }).style("left", function(d) {
        return d + "px";
    }).attr("class", "meddiv")
    // Add an id element to allow you to find this div outside of D3.
    .attr("id", function(d) { 
        return d;
     });

    // Tell D3 to remove all divs that no longer point to existing data.
    mediumdivs.exit().remove();   
}

// Draw the scene for the initial data array at the top.           
update([10, 50, 90, 130, 170, 210]);      
// Draw the scene with the updated array.
update([30, 80, 90, 130, 170, 210]);

我不确定 D3 如何存储索引的内部工作原理,但您可以id向您创建的 div 添加一个属性,以便为自己创建唯一索引。

于 2012-07-18T18:00:40.493 回答
0

到目前为止给出的其他答案使用删除和重新创建 div 的策略。这是没有必要的。Al R. 的原始代码的问题在于它使用data密钥的方式。旧数据和新传入的数据都使用相同的data键函数。因为在 Al R. 的示例中,旧数据是一个简单的数字数组,而新数据是一个具有属性的对象数组,该行中没有选择数据。mediumUpdate

这是使选择起作用的一种方法:

var newdata = [10, 50];
var newdatamap = {10:30, 50:80};
var mediumUpdate = mediumdivs.data(newdata, function(d){return d;})
    .style("left",function(d){return newdatamap[d] + "px";});

这是一个jsfiddle,它也会改变所选 div 的颜色以使效果明显。

于 2015-03-30T04:48:38.940 回答
0

在上面的答案中,需要一个更新步骤来转换具有相同键的 div。说明性 jsfiddle显示有/没有更新功能会发生什么。

更新函数只是 selection.stuff,而不是 selection.enter().stuff :

//add a container div to the body and add a class
var updateDiv = d3.select("#updateDiv").attr("class", "bluediv");
var noUpdateDiv = d3.select("#noUpdateDiv").attr("class", "bluediv");

function update(selection,data,zeroTop,withUpdate) {
    //add six medium-sized divs to the container div
    //note that a key index function is provided to the data method here
    //where do the resulting index value get stored?
    var mediumdivs = selection.selectAll("div").data(data, function(d) {
        return d;
    });

    if(withUpdate){
        mediumdivs.style("top", function(d) {
            if(zeroTop){
                return 0
            }else{
                return d + "px";
            }        
        }).style("left", function(d) {
            return d + "px";
        }).attr("class", "meddiv");
    }


    mediumdivs.enter().append("div").style("top", function(d) {
        if(zeroTop){
            return 0
        }else{
            return d + "px";
        }        
    }).style("left", function(d) {
        return d + "px";
    }).attr("class", "meddiv");

    mediumdivs.exit().remove();   
}
//with the update function we maintain 3 of the old divs, and move them to the top
update(updateDiv,[10, 50, 90, 130, 170, 210],false,true);      
update(updateDiv,[10,50,90],true,true);

//without the update function divs are maintained, but not transitioned
update(noUpdateDiv,[10, 50, 90, 130, 170, 210],false,false);      
update(noUpdateDiv,[10,50,90],true,false);    
于 2015-03-29T22:47:31.103 回答