d3:基于滑块值添加和删除force.nodes [英] d3: Adding and removing force.nodes based on slider values

查看:247
本文介绍了d3:基于滑块值添加和删除force.nodes的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

一段时间后,我在根据用户输入来添加和删除节点时遇到了一些困难,这是通过每次用户从复选框列表中选择要查看的对象时更新被推送到force.nodes()中的整个对象集来解决的

I had some difficulty a while back adding and removing nodes based on user input which was solved by updating the entire set of objects pushed into force.nodes() each time the user selected which they wanted to view from a list of checkboxes.

但是,我认为从滑块进行更新需要更精细的操作-我不想每次移动滑块时都更新整个设置.我想将节点从力.nodes()中推入和弹出.

Updating from a slider however I think requires a more finesse touch - I don't want to update the entire set every time the slider is moved. I want to push and pop nodes in and out of force.nodes().

使用我当前的代码,节点可以正常运行-它们只是不回去.jsfiddle在这里-

With my current code the nodes are coming out just fine - they're just not going back in. jsfiddle here - https://jsfiddle.net/hiwilson1/ancmtxux/3/

这是引起问题的部分;

This is the part causing problems;

function brushed() {
    var exists;

    //var newd = new Date(2013, 05, 01)

    data.forEach(function(d, i) {
        //if data point in range (between extent 0 and 1)
        if (d.date >= brush.extent()[0] && d.date <= brush.extent()[1]) {
            exists = force.nodes().some(function(node, i) {
                //check if data point already exists in force.nodes()
                return (node.mIndex == d.mIndex)                
                })
            console.log(exists)
            if (!exists) {
                force.nodes().push(d)
            }
        }
        else {
            force.nodes().splice(i, 1)
        }   
    })



    d3.select("#nodeCount").text(force.nodes().length)
}

对于每个数据点,我都在检查该点是否位于extent()[0]和[1]之间.如果是这样,则检查force.nodes()以查看它当前是否是那里的成员.如果不是,则将其推入force.nodes().

For each data point, I'm checking whether or not the point lies between extent()[0] and [1]. If it does, then check force.nodes() to see if it's currently a member there. If it isn't, then push it into force.nodes().

如果数据点不在扩展区之间,则从force.nodes()进行拼接.最后一点工作正常.

If the data point doesn't lie between the extents then splice it from force.nodes(). This last bit works just fine.

更新:已修复.实际上,我还研究了如何过滤附加到节点的链接. jsfiddle此处- https://jsfiddle.net/hiwilson1/7oumeat5/2/.永远不要尝试对索引/硬编码索引执行此操作,将节点/链接作为对象进行比较.

UPDATE: Fixed. I actually also worked out how to filter links attached to nodes as well. jsfiddle here - https://jsfiddle.net/hiwilson1/7oumeat5/2/. Never try and do this with indexes/hard coded indexes, compare the nodes/links as objects.

偶然地,我看到了节点顶部的链接.如果有解决方法,我很乐意听到.

Incidentally I'm seeing links over the top of nodes. If there's some way to fix this I'd be happy to hear it.

进一步更新:为确保节点后的链接使用.insert("line",:first-child")代替.append("line")

FURTHER UPDATE: To ensure links behind nodes use .insert("line", ":first-child") in place of .append("line")

推荐答案

您当前的代码存在一些问题.根本的问题是您要将data赋予force.nodes(),这意味着两个数据结构实际上是相同的.也就是说,当您从force.nodes()中删除元素时,您也在修改底层的data.因此,您无法将它们重新添加回-它们不见了.

There are a few problems with your current code. The fundamental problem is that you're giving data to force.nodes(), which means that the two data structures are actually the same. That is, when you're removing elements from force.nodes(), you're modifying the underlying data as well. Hence you can't add them back -- they're gone.

通过将data的副本传递给force.nodes()可以很容易地解决此问题:

This is easily fixed by passing a copy of data to force.nodes():

var force = d3.layout.force()
    .nodes(JSON.parse(JSON.stringify(data)))

然后您要从force.nodes()中删除错误的节点-您正在使用的索引用于data,而不是force.nodes().您可以计算force.nodes()data元素的索引并像这样使用它:

Then you're removing the wrong nodes from force.nodes() -- the index you're using is for data, not force.nodes(). You can compute the index of the data element in force.nodes() and use it like this:

data.forEach(function(d, i) {
        var idx = -1;
        force.nodes().forEach(function(node, j) {
            if(node.mIndex == d.mIndex) {
                idx = j;
            }
        });
        //if data point in range (between extent 0 and 1)
        if (d.date >= brush.extent()[0] && d.date <= brush.extent()[1]) {
            if (idx == -1) {
                force.nodes().push(d)
            }
        }
        else if(idx > -1) {
            force.nodes().splice(idx, 1)
        }

最后,您需要在brushed的末尾调用force.start(),以使布局确定下来后更改变得可见.

Finally, you need to call force.start() at the end of brushed for the changes to become visible after the layout has settled down.

完整示例此处.

这篇关于d3:基于滑块值添加和删除force.nodes的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆