【问题标题】:Filter d3 SVG by JSON Attribute Based on Dropdown基于下拉列表的 JSON 属性过滤 d3 SVG
【发布时间】:2017-12-09 10:19:02
【问题描述】:

我有力有向图的节点和链接数据。节点之间可能有一个、两个或三个链接:

{"nodes": [{"id": "Michael Scott", "numOfLinks": 1}
          ,{"id": "Jim Halpert", "numOfLinks": 1}
          ,{"id": "Pam Beasley", "numOfLinks": 2}
          ,{"id": "Kevin Malone", "numOfLinks": 2}
          ,{"id": "Angela", "numOfLinks": 3}
          ,{"id": "Dwight Schrute", "numOfLinks": 3}]
,"links": [{"source": "Michael Scott", "target": "Jim Halpert", "type": "red"}
          ,{"source": "Pam Beasley", "target": "Kevin Malone", "type": "red"}
          ,{"source": "Pam Beasley", "target": "Kevin Malone", "type": "white"}
          ,{"source": "Angela", "target": "Dwight Schrute", "type": "red"}
          ,{"source": "Angela", "target": "Dwight Schrute", "type": "white"}
          ,{"source": "Angela", "target": "Dwight Schrute", "type": "blue"}]
}

我有一个 HTML 下拉菜单供用户过滤掉没有一定数量链接的节点(和相应的链接):

<select id="selectLinkNumber" name="selectLinkNumber">
     <option value="1">All</option>
     <option value="2">Two or More Links</option>
     <option value="3">Three or More Links</option>
</select>

我已将此下拉列表合并到我的 d3 代码中:

var dropdown = d3.select("#selectLinkNumber")
var change = function() {
d3.selectAll("svg > *").remove()
var val = dropdown.node().options[dropdown.node().selectedIndex].value;

d3.json("test.json", function(error, graph) {
    //do stuff
    })
}
dropdown.on("change", change)
change();

这会导致一个图表被删除,并在从下拉列表中进行新选择时重新出现。目标是只显示值大于或等于选择的节点。例如,如果选择“三”,则仅显示 Angela、Dwight 和他们的三个链接。如果选择“二”,则选择 Pam、Kevin、Angela、Dwight 及其对应的链接。

从逻辑上讲,我认为需要根据vald3.json("test.json", function(error, graph) { 行之后直接过滤test.json 数据。但是,我不确定如何有效地完成此任务。这个示例 (https://jsfiddle.net/tgv6s5cd/14/) 基本上可以满足我的要求,但我无法通过手动数据创建和众多功能找到自己的方式。我认为在引入test.json后过滤一次会更简单

一旦用户进行下拉选择,我应该如何过滤数据?

【问题讨论】:

    标签: javascript html json d3.js svg


    【解决方案1】:

    这是 Javascript 中的基本数组操作。 graph 毕竟只是一个有两个数组属性的对象。

    d3.json("test.json", function(error, graph) {
        var filteredNodes = graph.nodes.filter(d => d.numOfLinks >= val);
        var names = filteredNodes.map(d => d.id);
        var filteredLinks = graph.links.filter((d) => {
            return (names.indexOf(d.source) >= 0) || 
                   (names.indexOf(d.target) >= 0)
        });
    
        var filteredGraph = {
            nodes: filteredNodes,
            links: filteredLinks
        };
        // render
    })
    

    【讨论】:

    • 非常感谢您的帮助。如果value 在链接数组中,该代码将如何变化?
    • 我将第一行改为var filteredLinks = graph.links.filter(d =&gt; d.numOfLinks &gt;= val);,我相信var filteredGraph 会保持不变。只是不确定如何映射回节点,因为它们只有 id 而不是 sourcetarget
    猜你喜欢
    • 2016-04-23
    • 1970-01-01
    • 1970-01-01
    • 2018-10-04
    • 1970-01-01
    • 1970-01-01
    • 2019-09-12
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多