javascript - D3 js点击同时触发所有过去的点击

标签 javascript jquery html d3.js

我从 d3js 开始并尝试创建一个图形数据结构。

代码如下(抱歉,代码太多,无法找到将其分解以用于演示目的的方法)。 所以就这样吧。

 var nodeNumber = 1;
    $(document).ready(function() {


        var graphContainer = d3.select(".graph-diagram").append("svg").attr("width", 1500).attr("height", 600).attr("class", "graph-container");
        //CreateNode(nodeId,nodeLabel,className,nodeType)
        var root = CreateNode(nodeNumber, "root", "head", "root");
        
        //creating children initially

        CreateChild(nodeNumber, "child", "head", "rightchild", "1");
        CreateChild(nodeNumber, "child", "head", "leftchild", "1");
        CreateChild(nodeNumber, "child", "head", "leftchild", "1");
        //CreateChild("5","child","head","rightchild","1");



        //creating edges initially
        CreateEdge("1", "2", "label");
        CreateEdge("1", "3", "label");
        CreateEdge("1", "4", "label");
        //CreateEdge("1","5","label");



    });



  //function to calculate position of new node , can be ignored
    function CalculatePosition(nodeType, parentId) {
        var positions = {};
        var noOfChildren = parseInt($("rect[nodeId=" + parentId + "]").attr('children'));

        if (nodeType == "root") {
            positions.positionX = parseInt($(".graph-container").attr('width')) / 2;
            positions.positionY = parseInt($(".graph-container").attr('height')) / 2;
        } else {
            if (noOfChildren % 2 == 0) {

                if (nodeType == "rightchild") {

                    positions.positionY = parseInt($("rect[nodeId=" + parentId + "]").attr('y')) - 100;
                    positions.positionX = parseInt($("rect[nodeId=" + parentId + "]").attr('x')) + 300;
                } else if (nodeType == "leftchild") {

                    positions.positionY = parseInt($("rect[nodeId=" + parentId + "]").attr('y')) - 100;
                    positions.positionX = parseInt($("rect[nodeId=" + parentId + "]").attr('x')) - 300;
                }
            } else {
                if (nodeType == "rightchild") {

                    positions.positionY = parseInt($("rect[nodeId=" + parentId + "]").attr('y')) + 100;
                    positions.positionX = parseInt($("rect[nodeId=" + parentId + "]").attr('x')) + 300;
                } else if (nodeType == "leftchild") {

                    positions.positionY = parseInt($("rect[nodeId=" + parentId + "]").attr('y')) + 100;
                    positions.positionX = parseInt($("rect[nodeId=" + parentId + "]").attr('x')) - 300;
                }

            }
        }

        return positions;
    }


    //create root node , click function is inside this (executes only one time)
    function CreateNode(nodeId, nodeLabel, className, nodeType) {
        var node = d3.select("svg").append('g');

        var positions = CalculatePosition(nodeType);

        node.append("rect")
            .attr("x", positions.positionX)
            .attr("y", positions.positionY)
            .attr("height", 50)
            .attr("width", 200)
            .attr("rx", 30)
            .attr("ry", 30)
            .attr("nodeId", nodeId)
            .attr("children", "0")
            .style("fill", "#f1f1f1")
            .style("stroke", "none");

        node.append("text")
            .attr("x", positions.positionX + 100)
            .attr("y", positions.positionY + 30)
            .attr("text-anchor", "middle")
            .style("font-size", "24px")
            .attr('fill', '#444')
            .text(nodeLabel);

        var addchild = node.append("g");

        addchild.append("circle")
            .attr("cx", positions.positionX + 170)
            .attr("cy", positions.positionY + 25)
            .attr("r", 10)
            .attr("class", "addchild")
            .style("fill", "white")
            .style("stroke", "#444")
            .style("stroke-width", "2");

        addchild.append("line")
            .attr("x1", positions.positionX + 162)
            .attr("y1", positions.positionY + 25)
            .attr("x2", positions.positionX + 178)
            .attr("y2", positions.positionY + 25)
            .attr("stroke", "#444")
            .style("stroke-width", "2");

        addchild.append("line")
            .attr("x1", positions.positionX + 170)
            .attr("y1", positions.positionY + 17)
            .attr("x2", positions.positionX + 170)
            .attr("y2", positions.positionY + 33)
            .attr("stroke", "#444")
            .style("stroke-width", "2");


        //click function that executes only one time. ( for adding in root alone)

        addchild.on("click", function() {

        	 $("#child-info").show();

            $("#btn-add-child").click(function() {

                var parentX = parseInt($("rect[nodeId=1]").attr('x'));
                var childType;

                if (positions.positionX < parentX) {
                    childType = "leftchild";
                } else {
                    childType = "rightchild";
                }

                CreateChild(nodeNumber, $("#child-text").val(), "head", childType, nodeId);
                CreateEdge("1", nodeNumber - 1, $("#child-label").val());
                $("#child-info").hide();
            });

           

        });;


        nodeNumber++;
        return node;

    }




    //create children   **********click function where the problem might be************ 

    function CreateChild(nodeId, nodeLabel, className, nodeType, parentId) {
        var node = d3.select("svg").append('g');
        var positions = CalculatePosition(nodeType, parentId);

        // create rounded rectangle
        node.append("rect")
            .attr("x", positions.positionX)
            .attr("y", positions.positionY)
            .attr("height", 40)
            .attr("width", 200)
            .attr("rx", 20)
            .attr("ry", 20)
            .attr("nodeId", nodeId)
            .attr("children", "0")
            .style("fill", "#f1f1f1")
            .style("stroke", "none")
            .transition()
            .duration(750);

        //add text

        node.append("text")
            .attr("x", positions.positionX + 50)
            .attr("y", positions.positionY + 30)
            .attr("text-anchor", "middle")
            .style("font-size", "24px")
            .attr('fill', '#444')
            .text(nodeLabel);

        //add plus symbol can be ignored

        var addchild = node.append("g");

        addchild.append("circle")
            .attr("cx", positions.positionX + 170)
            .attr("cy", positions.positionY + 25)
            .attr("r", 10)
            .attr("class", "addchild")
            .style("fill", "white")
            .style("stroke", "#444")
            .style("stroke-width", "2");

        addchild.append("line")
            .attr("x1", positions.positionX + 162)
            .attr("y1", positions.positionY + 25)
            .attr("x2", positions.positionX + 178)
            .attr("y2", positions.positionY + 25)
            .attr("stroke", "#444")
            .style("stroke-width", "2");

        addchild.append("line")
            .attr("x1", positions.positionX + 170)
            .attr("y1", positions.positionY + 17)
            .attr("x2", positions.positionX + 170)
            .attr("y2", positions.positionY + 33)
            .attr("stroke", "#444")
            .style("stroke-width", "2");

            // **********click function where the problem might be************ 

        addchild.on("click", function() {
        	 $("#child-info").show();

            $("#btn-add-child").click(function() {



                console.log("nodenumber=" + nodeNumber);
                console.log("nodeid=" + nodeId);



                var parentX = parseInt($("rect[nodeId=1]").attr('x'));
                var childType;



                if (positions.positionX < parentX) {
                    childType = "leftchild";
                } else {
                    childType = "rightchild";
                }

                CreateChild(nodeNumber, $("#child-text").val(), "head", childType, nodeId);
                CreateEdge(nodeId, nodeNumber - 1, $("#child-label").val());
                $("#child-info").hide();;
            });
           

        });;

        var noOfChildren = parseInt($("rect[nodeId=" + parentId + "]").attr('children'));

        noOfChildren = noOfChildren + 1;

        $("rect[nodeId=" + parentId + "]").attr("children", String(noOfChildren));
        nodeNumber++;

    }

    // function to calculate data for drawing edges , can be ignored

    function CalculateEdgeData(nodeId1, nodeId2) {

        var node1x = parseInt($("rect[nodeId=" + nodeId1 + "]").attr('x'));
        var node1y = parseInt($("rect[nodeId=" + nodeId1 + "]").attr('y'));

        var node2x = parseInt($("rect[nodeId=" + nodeId2 + "]").attr('x'));
        var node2y = parseInt($("rect[nodeId=" + nodeId2 + "]").attr('y'));


        if (node1x < node2x) {
            //right
            node1x = node1x + 200;
            node1y = node1y + 25;
            node2y = node2y + 25;
        } else {
            //left
            node1x = node1x;
            node1y = node1y + 25;
            node2y = node2y + 25;
            node2x = node2x + 200;
        }
        return [{
            "x": node1x,
            "y": node1y
        }, {
            "x": node2x,
            "y": node2y
        }];

    }

    //function to draw the edge , can be ignored

    function CreateEdge(nodeId1, nodeId2, edgeLabel) {

        var curveData = CalculateEdgeData(nodeId1, nodeId2);



        //diagonal function
        var edge = d3.select("svg").append('g');
        var diagonal = d3.svg.diagonal()
            .source(function(d) {
                return {
                    "x": d[0].y,
                    "y": d[0].x
                };
            })
            .target(function(d) {
                return {
                    "x": d[1].y,
                    "y": d[1].x
                };
            })
            .projection(function(d) {
                return [d.y, d.x];
            });

        var curve = edge
            .datum(curveData)
            .append("path")
            .attr("class", "link")
            .transition()
            .duration("750")
            .attr("d", diagonal);

        curve
            .attr("stroke", "#70dbdb")
            .attr("stroke-width", 2)
            .attr("fill", "none");

        edge.append("text")
            .attr("x", parseInt(curveData[0].x) + parseInt(curveData[1].x) / 3)
            .attr("y", parseInt(curveData[0].y) + parseInt(curveData[1].y) / 2)
            .attr("text-anchor", "middle")
            .style("font-size", "18px")
            .attr('fill', '#444')
            .attr("transform", "translate(-270,-170)")
            .text(edgeLabel);


    }
#child-info {
  background: #f1f1f1;
  width: 500px;
  height: auto;
  position: fixed;
  padding: 10px;
  display: none;
}
#btn-add-child {
  background: #444;
  color: #fff;
  border: none;
  z-index: 100;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

  <div id="child-info">

        <input type="text" id="child-text" placeholder="child name">
        <input type="text" id="child-label" placeholder="label">
        <button id="btn-add-child">add</button>
    </div>
    <div class="graph-diagram">
    </div>

在这里,我尝试通过单击按钮添加新节点。 问题是当我第一次单击一个添加按钮时, child 被添加。当我单击另一个添加按钮时,第二次将节点添加到我之前单击的节点和现在单击的节点。 (函数被调用两次)第三次单击时,将为之前的所有添加执行函数。 我怀疑点击事件的绑定(bind)出了问题。我做错了什么?

(请参阅代码片段并尝试在不同位置添加节点以理解我的意思)

为了便于查看代码,我对部分代码以及可以忽略的部分进行了注释,因为它与上述问题无关。

谢谢。

最佳答案

这是因为每次绑定(bind)点击事件时都绑定(bind)$("#btn-add-child").click(function() {,可以在绑定(bind)前使用取消绑定(bind)点击事件$("#btn-add-child").off('click');。尝试以下代码:-

 var nodeNumber = 1;
    $(document).ready(function() {


        var graphContainer = d3.select(".graph-diagram").append("svg").attr("width", 1500).attr("height", 600).attr("class", "graph-container");
        //CreateNode(nodeId,nodeLabel,className,nodeType)
        var root = CreateNode(nodeNumber, "root", "head", "root");
        
        //creating children initially

        CreateChild(nodeNumber, "child", "head", "rightchild", "1");
        CreateChild(nodeNumber, "child", "head", "leftchild", "1");
        CreateChild(nodeNumber, "child", "head", "leftchild", "1");
        //CreateChild("5","child","head","rightchild","1");



        //creating edges initially
        CreateEdge("1", "2", "label");
        CreateEdge("1", "3", "label");
        CreateEdge("1", "4", "label");
        //CreateEdge("1","5","label");



    });



  //function to calculate position of new node , can be ignored
    function CalculatePosition(nodeType, parentId) {
        var positions = {};
        var noOfChildren = parseInt($("rect[nodeId=" + parentId + "]").attr('children'));

        if (nodeType == "root") {
            positions.positionX = parseInt($(".graph-container").attr('width')) / 2;
            positions.positionY = parseInt($(".graph-container").attr('height')) / 2;
        } else {
            if (noOfChildren % 2 == 0) {

                if (nodeType == "rightchild") {

                    positions.positionY = parseInt($("rect[nodeId=" + parentId + "]").attr('y')) - 100;
                    positions.positionX = parseInt($("rect[nodeId=" + parentId + "]").attr('x')) + 300;
                } else if (nodeType == "leftchild") {

                    positions.positionY = parseInt($("rect[nodeId=" + parentId + "]").attr('y')) - 100;
                    positions.positionX = parseInt($("rect[nodeId=" + parentId + "]").attr('x')) - 300;
                }
            } else {
                if (nodeType == "rightchild") {

                    positions.positionY = parseInt($("rect[nodeId=" + parentId + "]").attr('y')) + 100;
                    positions.positionX = parseInt($("rect[nodeId=" + parentId + "]").attr('x')) + 300;
                } else if (nodeType == "leftchild") {

                    positions.positionY = parseInt($("rect[nodeId=" + parentId + "]").attr('y')) + 100;
                    positions.positionX = parseInt($("rect[nodeId=" + parentId + "]").attr('x')) - 300;
                }

            }
        }

        return positions;
    }


    //create root node , click function is inside this (executes only one time)
    function CreateNode(nodeId, nodeLabel, className, nodeType) {
        var node = d3.select("svg").append('g');

        var positions = CalculatePosition(nodeType);

        node.append("rect")
            .attr("x", positions.positionX)
            .attr("y", positions.positionY)
            .attr("height", 50)
            .attr("width", 200)
            .attr("rx", 30)
            .attr("ry", 30)
            .attr("nodeId", nodeId)
            .attr("children", "0")
            .style("fill", "#f1f1f1")
            .style("stroke", "none");

        node.append("text")
            .attr("x", positions.positionX + 100)
            .attr("y", positions.positionY + 30)
            .attr("text-anchor", "middle")
            .style("font-size", "24px")
            .attr('fill', '#444')
            .text(nodeLabel);

        var addchild = node.append("g");

        addchild.append("circle")
            .attr("cx", positions.positionX + 170)
            .attr("cy", positions.positionY + 25)
            .attr("r", 10)
            .attr("class", "addchild")
            .style("fill", "white")
            .style("stroke", "#444")
            .style("stroke-width", "2");

        addchild.append("line")
            .attr("x1", positions.positionX + 162)
            .attr("y1", positions.positionY + 25)
            .attr("x2", positions.positionX + 178)
            .attr("y2", positions.positionY + 25)
            .attr("stroke", "#444")
            .style("stroke-width", "2");

        addchild.append("line")
            .attr("x1", positions.positionX + 170)
            .attr("y1", positions.positionY + 17)
            .attr("x2", positions.positionX + 170)
            .attr("y2", positions.positionY + 33)
            .attr("stroke", "#444")
            .style("stroke-width", "2");


        //click function that executes only one time. ( for adding in root alone)

        addchild.on("click", function() {

        	 $("#child-info").show();
            $("#btn-add-child").off('click');
            $("#btn-add-child").on('click',function() {

                var parentX = parseInt($("rect[nodeId=1]").attr('x'));
                var childType;

                if (positions.positionX < parentX) {
                    childType = "leftchild";
                } else {
                    childType = "rightchild";
                }

                CreateChild(nodeNumber, $("#child-text").val(), "head", childType, nodeId);
                CreateEdge("1", nodeNumber - 1, $("#child-label").val());
                $("#child-info").hide();
            });

           

        });;


        nodeNumber++;
        return node;

    }




    //create children   **********click function where the problem might be************ 

    function CreateChild(nodeId, nodeLabel, className, nodeType, parentId) {
        var node = d3.select("svg").append('g');
        var positions = CalculatePosition(nodeType, parentId);

        // create rounded rectangle
        node.append("rect")
            .attr("x", positions.positionX)
            .attr("y", positions.positionY)
            .attr("height", 40)
            .attr("width", 200)
            .attr("rx", 20)
            .attr("ry", 20)
            .attr("nodeId", nodeId)
            .attr("children", "0")
            .style("fill", "#f1f1f1")
            .style("stroke", "none")
            .transition()
            .duration(750);

        //add text

        node.append("text")
            .attr("x", positions.positionX + 50)
            .attr("y", positions.positionY + 30)
            .attr("text-anchor", "middle")
            .style("font-size", "24px")
            .attr('fill', '#444')
            .text(nodeLabel);

        //add plus symbol can be ignored

        var addchild = node.append("g");

        addchild.append("circle")
            .attr("cx", positions.positionX + 170)
            .attr("cy", positions.positionY + 25)
            .attr("r", 10)
            .attr("class", "addchild")
            .style("fill", "white")
            .style("stroke", "#444")
            .style("stroke-width", "2");

        addchild.append("line")
            .attr("x1", positions.positionX + 162)
            .attr("y1", positions.positionY + 25)
            .attr("x2", positions.positionX + 178)
            .attr("y2", positions.positionY + 25)
            .attr("stroke", "#444")
            .style("stroke-width", "2");

        addchild.append("line")
            .attr("x1", positions.positionX + 170)
            .attr("y1", positions.positionY + 17)
            .attr("x2", positions.positionX + 170)
            .attr("y2", positions.positionY + 33)
            .attr("stroke", "#444")
            .style("stroke-width", "2");

            // **********click function where the problem might be************ 

        addchild.on("click", function() {
        	 $("#child-info").show();
             $("#btn-add-child").off('click');
             $("#btn-add-child").on('click',function() {



                console.log("nodenumber=" + nodeNumber);
                console.log("nodeid=" + nodeId);



                var parentX = parseInt($("rect[nodeId=1]").attr('x'));
                var childType;



                if (positions.positionX < parentX) {
                    childType = "leftchild";
                } else {
                    childType = "rightchild";
                }

                CreateChild(nodeNumber, $("#child-text").val(), "head", childType, nodeId);
                CreateEdge(nodeId, nodeNumber - 1, $("#child-label").val());
                $("#child-info").hide();;
            });
           

        });;

        var noOfChildren = parseInt($("rect[nodeId=" + parentId + "]").attr('children'));

        noOfChildren = noOfChildren + 1;

        $("rect[nodeId=" + parentId + "]").attr("children", String(noOfChildren));
        nodeNumber++;

    }

    // function to calculate data for drawing edges , can be ignored

    function CalculateEdgeData(nodeId1, nodeId2) {

        var node1x = parseInt($("rect[nodeId=" + nodeId1 + "]").attr('x'));
        var node1y = parseInt($("rect[nodeId=" + nodeId1 + "]").attr('y'));

        var node2x = parseInt($("rect[nodeId=" + nodeId2 + "]").attr('x'));
        var node2y = parseInt($("rect[nodeId=" + nodeId2 + "]").attr('y'));


        if (node1x < node2x) {
            //right
            node1x = node1x + 200;
            node1y = node1y + 25;
            node2y = node2y + 25;
        } else {
            //left
            node1x = node1x;
            node1y = node1y + 25;
            node2y = node2y + 25;
            node2x = node2x + 200;
        }
        return [{
            "x": node1x,
            "y": node1y
        }, {
            "x": node2x,
            "y": node2y
        }];

    }

    //function to draw the edge , can be ignored

    function CreateEdge(nodeId1, nodeId2, edgeLabel) {

        var curveData = CalculateEdgeData(nodeId1, nodeId2);



        //diagonal function
        var edge = d3.select("svg").append('g');
        var diagonal = d3.svg.diagonal()
            .source(function(d) {
                return {
                    "x": d[0].y,
                    "y": d[0].x
                };
            })
            .target(function(d) {
                return {
                    "x": d[1].y,
                    "y": d[1].x
                };
            })
            .projection(function(d) {
                return [d.y, d.x];
            });

        var curve = edge
            .datum(curveData)
            .append("path")
            .attr("class", "link")
            .transition()
            .duration("750")
            .attr("d", diagonal);

        curve
            .attr("stroke", "#70dbdb")
            .attr("stroke-width", 2)
            .attr("fill", "none");

        edge.append("text")
            .attr("x", parseInt(curveData[0].x) + parseInt(curveData[1].x) / 3)
            .attr("y", parseInt(curveData[0].y) + parseInt(curveData[1].y) / 2)
            .attr("text-anchor", "middle")
            .style("font-size", "18px")
            .attr('fill', '#444')
            .attr("transform", "translate(-270,-170)")
            .text(edgeLabel);


    }
#child-info {
  background: #f1f1f1;
  width: 500px;
  height: auto;
  position: fixed;
  padding: 10px;
  display: none;
}
#btn-add-child {
  background: #444;
  color: #fff;
  border: none;
  z-index: 100;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/d3/3.4.11/d3.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

  <div id="child-info">

        <input type="text" id="child-text" placeholder="child name">
        <input type="text" id="child-label" placeholder="label">
        <button id="btn-add-child">add</button>
    </div>
    <div class="graph-diagram">
    </div>

关于javascript - D3 js点击同时触发所有过去的点击,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34633738/

相关文章:

javascript - jQuery:如果你不知道它们的名字,请阅读所有域 cookie

javascript - 在执行之前测试 JavaScript 表达式是否格式良好

jquery - 内联日期选择器的不引人注目的验证不起作用,对于非内联日期选择器工作正常

javascript - vuejs MaterializeCSS timepicker 没有获取值

javascript - 滚动顶部不工作

css - 将 div 移动到新行

javascript - 访问作用域外的 JavaScript 变量

javascript - 如何使用 JS 变量作为参数执行 sql 查询

c# - ASP.Net 中的不一致外观

html - 如何在按钮文本上添加渐变颜色?