javascript - 无法读取未定义的属性 'weight' 和无法读取未定义的属性 'x' d3.js

标签 javascript json d3.js svg

我在这里创建了一个 fiddle 来复制这个问题:fiddle link

在此之前,我们在项目中使用了一个很好的平面 json 文件。我必须使用的新文件嵌套得更多。

我的 d3 函数如下所示:

/* chart data */
// return data for relationships between database tables
returnTableRelationshipData = function(){

    var url = 'https://api.myjson.com/bins/7ovnb.json';
    d3.json(url, function(data){

        //find the node index
        function find(f){
          var i = -1
            data.p.nodes.forEach(function(node, index){
                node.x = 200 + Math.random()*200;
                node.y = 150 + Math.random()*200;
                if(node.properties.nodeID.val == f)
                    i = index;
            });
            return i;
        }

        //set the source and target index
        data.p.relationships.forEach(function(d){
            d.start = find(d.start);
            d.end = find(d.end);
        });

        // used to store the number of links between two nodes. 
        var mLinkNum = {};

        // sort links first
        sortLinks();                                

        // set up linkIndex and linkNumer, because it may possible multiple links share the same source and target node
        setLinkIndexAndNum();

        // check that we don't have empty or null values
        checkDataNotEmpty();

        var w = 1000;
        var h = 400;

        var force = d3.layout.force()
            .nodes(data.p.nodes)
            .links(data.p.relationships)
            .alpha(.1)
            .gravity(1)
            .charge(-10000)
            .size([w, h])
            .start();

        var svg = d3.select('.node-wrapper').append('svg')
            .attr('width', w)
            .attr('height', h);

        var path = svg.append('svg:g')
            .selectAll('path')
            .data(force.links())
            .enter().append('line')
            .attr('class', 'link')
            .attr('x1', function(d) {
                return d.start.x;
            })
            .attr('y1', function(d) {
                return d.start.y;
            })
            .attr('x2', function(d) {
                return d.end.x;
            })
            .attr('y2', function(d) {
                return d.end.y;
            });

        var node_drag = d3.behavior.drag()
            .on('dragstart', dragstart)
            .on('drag', dragmove)
            .on('dragend', dragend);

        var circle = svg.append('svg:g')
            .selectAll('circle')
            .data(force.nodes())
            .enter().append('svg:circle')
            .attr('r', 6)
            .call(node_drag);

        var text = svg.append('svg:g')                                
            .selectAll('g')
            .data(force.nodes())
            .enter().append('svg:g');

        text.append('svg:text')
            .text(function(d){ 
                return d.description;
            });

        force.on('tick', tick);

        function tick() {
            path.attr('x1', function(d) {
                return d.start.x;
            })
            .attr('y1', function(d) {
                return d.start.y;
            })
            .attr('x2', function(d) {
                return d.end.x;
            })
            .attr('y2', function(d) {
                return d.end.y;
            });

            circle.attr('transform', function(d){
                return 'translate(' + d.x + ',' + d.y + ')';
            });

            text.attr('transform', function(d){
                return 'translate(' + d.x + ',' + d.y + ')';
            });
        }

        function dragstart(d, i) {
            force.stop(); // stops the force auto positioning before you start dragging
        }

        function dragmove(d, i) {
            d.px += d3.event.dx;
            d.py += d3.event.dy;
            d.x += d3.event.dx;
            d.y += d3.event.dy;
            tick();
        }

        function dragend(d, i) {
            d.fixed = true; // of course set the node to fixed so the force doesn't include the node in its auto positioning stuff
            tick();
        }

        // sort the links by source, then target
        function sortLinks(){
            if(data.p.relationships != null){                         
                data.p.relationships.sort(function(a,b){
                    if(a.start > b.start){
                        return 1;
                    }else if(a.start < b.start){
                        return -1;
                    }else{
                        if(a.end > b.end){
                            return 1;
                        }if(a.end < b.end){
                            return -1;
                        }else{
                            return 0;
                        }
                    }
                });
            }
        }

        //any links with duplicate source and target get an incremented 'linknum'
        function setLinkIndexAndNum(){                              
            for(var i = 0; i < data.p.relationships.length; i++){
                if(i != 0 &&
                    data.p.relationships[i].start == data.p.relationships[i-1].start &&
                    data.p.relationships[i].end == data.p.relationships[i-1].end){
                    data.p.relationships[i].linkindex = data.p.relationships[i-1].linkindex + 1;
                }else{
                    data.p.relationships[i].linkindex = 1;
                }// save the total number of links between two nodes
                if(mLinkNum[data.p.relationships[i].end + ',' + data.p.relationships[i].start] !== undefined){
                    mLinkNum[data.p.relationships[i].end + ',' + data.p.relationships[i].start] = data.p.relationships[i].linkindex;
                }else{
                    mLinkNum[data.p.relationships[i].start + ',' + data.p.relationships[i].end] = data.p.relationships[i].linkindex;
                }
            }
        }

        function checkDataNotEmpty(){
            data.p.relationships.forEach(function(link, index, list) {
                if (typeof link.start === 'undefined') {
                    console.log('undefined link', data.p.nodes[link.start]);
                }
                if (typeof link.end === 'undefined') {
                    console.log('undefined source', data.p.nodes[link.end]);
                }
            });
        }

    });
}();

根据这个answer如果我注释掉这些行:

var force = d3.layout.force()
            //.nodes(data.p.nodes)
            //.links(data.p.relationships)
            .alpha(.1)
            .gravity(1)
            ...

然后将一个 svg 对象附加到 html。

链接的答案实际上并没有为此提供解决方案。

节点和链接似乎都得到了正确的迭代。 screenshot of nodes

我唯一的预感是我必须以某种方式将 "start""end" 映射到 sourcetarget,或者我需要以某种方式转换 data.p.nodesdata.p.relationships。或者索引可能无法正常工作。

我能够与后端开发人员合作更改一些 json 属性和类型(字符串、整数等)。

正在从此处调用 json 文件:http://myjson.com/7ovnb

最佳答案

  1. 为链接定义笔画以使其可见:

    .node-wrapper line {
      stroke: #0D9E1E;
    }
    
  2. 重命名所有出现的 .start.source.end.targettick() 函数中。

  3. 在您的 find() 函数中,您必须与 node.id 属性进行比较:

    function find(f){
      var i; // do not return an existing value as default
        data.p.nodes.forEach(function(node, index){
            node.x = 200 + Math.random()*200;
            node.y = 150 + Math.random()*200;
            if(node.id == f)
                i = index;
        });
        return i;
    }
    

    Index 0 if 是一个现有的节点索引,所以最好不要将其设置为默认值。

关于javascript - 无法读取未定义的属性 'weight' 和无法读取未定义的属性 'x' d3.js,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46927192/

相关文章:

javascript - ng-选择 AngularJS

javascript - 如何使用带有过渡缓进出效果的javascript隐藏/显示div?

.net - 如何通过 Net.WebRequest 正确发送 json 数据 - PowerShell

javascript - 将 d3.csv 响应分配给全局变量

d3.js - D3 从下拉菜单中选择新数据后如何更新图表

javascript - 如何使用 jQuery 选择具有特定文本的元素

javascript - 无法在 React Native 中显示数组

java - 谷歌地点 API 的 GSON 解析

c# - 将带方括号的字符串解析为json

javascript - 基本 d3js max 返回多个值