未捕获的TypeError:svg.selectAll不是D3.js强制布局中的函数

时间:2017-02-03 22:05:30

标签: javascript d3.js svg

我需要创建一个强制定向布局,可以像example一样进行更新。 另一方面,我需要在边缘使用标签的力布局以及每个边缘末端的箭头。为此,我尝试将此example与前一个{{3}}结合起来。 因此,为了使标签位于边缘和箭头中,我使用第二个示例的path。 到目前为止,这是我的代码:

<!DOCTYPE html>
<html>
<head>
    <title>Animating Changes in Force Diagram</title>
    <script src="http://d3js.org/d3.v3.min.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
    <style>
        .link {
            stroke: #2E2E2E;
            stroke-width: 2px;
        }

        .node {
            stroke: #fff;
            stroke-width: 2px;
        }

        .textClass {
            stroke: #323232;
            font-family: "Lucida Grande", "Droid Sans", Arial, Helvetica, sans-serif;
            font-weight: normal;
            stroke-width: .5;
            font-size: 14px;
        }

        .edgepath {
            stroke: #323232;
            font-family: "Lucida Grande", "Droid Sans", Arial, Helvetica, sans-serif;
            font-weight: normal;
            stroke-width: .5;
            font-size: 14px;
        }

        .aEnd{
            fill: #444;
            font-family: helvetica;
            font-size: 8pt;
        }
    </style>
</head>
<body>
<button onclick="addNodes()">Restart Animation</button>
<button onclick="addNode1()">Test</button>
<script>
    var graph;
    function myGraph() {

        // Add and remove elements on the graph object
        this.addNode = function (id) {
            nodes.push({"id": id});
            update();
        };

        this.removeNode = function (id) {
            var i = 0;
            var n = findNode(id);
            while (i < links.length) {
                if ((links[i]['source'] == n) || (links[i]['target'] == n)) {
                    links.splice(i, 1);
                }
                else i++;
            }
            nodes.splice(findNodeIndex(id), 1);
            update();
        };

        this.removeLink = function (source, target) {
            for (var i = 0; i < links.length; i++) {
                if (links[i].source.id == source && links[i].target.id == target) {
                    links.splice(i, 1);
                    break;
                }
            }
            update();
        };

        this.removeallLinks = function () {
            links.splice(0, links.length);
            update();
        };

        this.removeAllNodes = function () {
            nodes.splice(0, links.length);
            update();
        };

        this.addLink = function (source, target, value) {
            links.push({"source": findNode(source), "target": findNode(target), "value": value});
            update();
        };

        var findNode = function (id) {
            for (var i in nodes) {
                if (nodes[i]["id"] === id) return nodes[i];
            }
            ;
        };

        var findNodeIndex = function (id) {
            for (var i = 0; i < nodes.length; i++) {
                if (nodes[i].id == id) {
                    return i;
                }
            }
            ;
        };

        // set up the D3 visualisation in the specified element
        var w = 960, h = 450;

        var color = d3.scale.category10();

        var vis = d3.select("body")
                .append("svg:svg")
                .attr("width", w)
                .attr("height", h)
                .attr("id", "svg")
                .attr("pointer-events", "all")
                .attr("viewBox", "0 0 " + w + " " + h)
                .attr("perserveAspectRatio", "xMinYMid")
                .append('svg:g');

        var force = d3.layout.force();

        var nodes = force.nodes();
        var links = force.links();

        var update = function () {


            var link = vis.selectAll("line")
                    .data(links, function (d) {
                        return d.source.id + "-" + d.target.id;
                    });

            link.enter().append("line")
                    .attr("id", function (d) {
                        return d.source.id + "-" + d.target.id;
                    })
                    .attr('marker-end','url(#arrowhead)')
                    .style("stroke","#ccc")
                    .style("pointer-events", "none");


            link.exit().remove();

            var edgepaths = svg.selectAll(".edgepath")
                .data(links)
                .enter()
                .append('path')
                .attr({'d': function(d) {return 'M '+d.source.x+' '+d.source.y+' L '+ d.target.x +' '+d.target.y},
                    'class':'edgepath',
                    'fill-opacity':0,
                    'stroke-opacity':0,
                    'fill':'blue',
                    'stroke':'red',
                    'id':function(d,i) {return 'edgepath'+i}})
                .style("pointer-events", "none");

            var node = vis.selectAll("g.node")
                    .data(nodes, function (d) {
                        return d.id;
                    });

            var nodeEnter = node.enter().append("g")
                    .attr("class", "node")
                    .call(force.drag);

            nodeEnter.append("svg:circle")
                    .attr("r", 12)
                    .attr("id", function (d) {
                        return "Node;" + d.id;
                    })
                    .attr("class", "nodeStrokeClass")
                    .attr("fill", function(d) { return color(d.id); });

            nodeEnter.append("svg:text")
                    .attr("class", "textClass")
                    .attr("x", 14)
                    .attr("y", ".31em")
                    .text(function (d) {
                        return d.id;
                    });

            node.exit().remove();


            force.on("tick", function () {

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

                link.attr("x1", function (d) {
                    return d.source.x;
                })
                .attr("y1", function (d) {
                    return d.source.y;
                })
                .attr("x2", function (d) {
                    return d.target.x;
                })
                .attr("y2", function (d) {
                    return d.target.y;
                });

            });

            // Restart the force layout.
            force
                .gravity(.01)
                .charge(-80000)
                .friction(0)
                .linkDistance( function(d) { return d.value * 10 } )
                .size([w, h])
                .start();
        };


        // Make it all go
        update();
    }

    function drawGraph() {

        graph = new myGraph("#svgdiv");


        graph.addNode('Sophia');
        graph.addNode('Ryan');
        graph.addNode('Alex');
        graph.addNode('Daniel');
        graph.addNode('Too');

        graph.addLink('Alex', 'Ryan', '20');
        graph.addLink('Sophia', 'Ryan', '20');
        graph.addLink('Daniel', 'Ryan', '20');
        graph.addLink('Daniel', 'Too', '20');

        keepNodesOnTop();

    }

    drawGraph();

    // because of the way the network is created, nodes are created first, and links second,
    // so the lines were on top of the nodes, this just reorders the DOM to put the svg:g on top
    function keepNodesOnTop() {
        $(".nodeStrokeClass").each(function( index ) {
            var gnode = this.parentNode;
            gnode.parentNode.appendChild(gnode);
        });
    }

    function addNodes() {
        d3.select("svg")
                .remove();
         drawGraph();
    }

    function addNode1() {
        d3.select("svg")
            .remove();
        drawGraph();
        graph.addNode('Test1');
        graph.addNode('Test2');
        graph.addLink('Test1', 'Test2', '20');
        keepNodesOnTop();

    }
</script>
</body>
</html>

选择问题和path显示此错误:

Uncaught TypeError: svg.selectAll is not a function at update (combine2.html:148) 

因为这行代码:

var edgepaths = svg.selectAll(".edgepath")

1 个答案:

答案 0 :(得分:2)

未定义对象svg。你还没有创建它。但是您确实有一个对象vis,您可以在其中附加链接:

 var link = vis.selectAll("line")...

Vis是你的svg的选择,所以你需要将你的svg元素附加到它:

var vis = d3.select("body")
            .append("svg:svg")

对于你的edgepaths,试试:

var edgepaths = vis.selectAll(".edgepath")...

而不是:

var edgepaths = svg.selectAll(".edgepath")...