Javascript 如何使D3力有向图中的一个节点在拖动到该位置后保持在该位置

Javascript 如何使D3力有向图中的一个节点在拖动到该位置后保持在该位置,javascript,d3.js,drag-and-drop,force-layout,Javascript,D3.js,Drag And Drop,Force Layout,我有一个力定向图,在这里我可以显示一些数字之间的关系。我们可以在释放节点后拖动节点。节点将返回到原始位置。但这里我想我将拖动节点。到目前为止,我可以将所有节点拖到某个位置,而节点不会返回到原始位置,但我还需要与它们的链接 <!DOCTYPE html> <meta charset="utf-8"> <style> .link { fill: none; stroke: #666; stroke-width: 1.5px; } #licensing { f

我有一个力定向图,在这里我可以显示一些数字之间的关系。我们可以在释放节点后拖动节点。节点将返回到原始位置。但这里我想我将拖动节点。到目前为止,我可以将所有节点拖到某个位置,而节点不会返回到原始位置,但我还需要与它们的链接

<!DOCTYPE html>
<meta charset="utf-8">
<style>
.link {
fill: none;
stroke: #666;
stroke-width: 1.5px;
  }

#licensing {
fill: green;
}

.link.licensing {
stroke: green;
 }

.link.resolved {
stroke-dasharray: 0, 2 1;
 }

circle {
fill: #ccc;
stroke: #333;
stroke-width: 1.5px;
cursor: pointer;
 }

text {
font: 10px sans-serif;
pointer-events: none;
text-shadow: 0 1px 0 #fff, 1px 0 0 #fff, 0 -1px 0 #fff, -1px 0 0 #fff;
   }
 </style>
 <body>
<script src="http://d3js.org/d3.v3.min.js"></script>
<script>


    var links = [];
    var nodes = {};

    // Compute the distinct nodes from the links.

    var width = 960, height = 500;

    var svg = d3.select("body").append("svg").attr("width", width).attr(
            "height", height);

    // Per-type markers, as they don't inherit styles.
    svg.append("defs").selectAll("marker").data(
            [ "suit", "licensing", "resolved" ]).enter().append("marker")
            .attr("id", function(d) {
                return d;
            }).attr("viewBox", "0 -5 10 10").attr("refX", 15).attr("refY",
                    -1.5).attr("markerWidth", 6).attr("markerHeight", 6)
            .attr("orient", "auto").append("path").attr("d",
                    "M0,-5L10,0L0,5");


           d3.json(
                    "test.json",
                    function(error, directed) {

                         links=directed.links;


                        links.forEach(function(link) {
                            link.source = nodes[link.source]
                                    || (nodes[link.source] = {
                                        name : link.source
                                    });
                            link.target = nodes[link.target]
                                    || (nodes[link.target] = {
                                        name : link.target
                                    });
                        });

                        var force = d3.layout.force().nodes(
                                d3.values(nodes)).links(links).size(
                                [ width, height ]).linkDistance(60).charge(
                                -300).on("tick", tick).start();

                        var path = svg.append("g").selectAll("path").data(
                                force.links()).enter().append("path").attr(
                                "class", function(d) {
                                    return "link " + d.type;
                                }).attr("marker-end", function(d) {
                            return "url(#" + d.type + ")";
                        });

                        var circle = svg.append("g").selectAll("circle")
                                .data(force.nodes()).enter().append(
                                        "circle").attr("r", 6).call(d3.behavior.drag().origin(function(d) {
                                            return d;
                                        }).on("drag", function(d) {
                                            d.x = d3.event.x, d.y = d3.event.y;
                                            d3.select(this).attr("cx", d.x).attr("cy", d.y);

                                            link.filter(function(l) {
                                                return l.source === d;
                                            }).attr("x1", d.x).attr("y1", d.y);

                                            link.filter(function(l) {
                                                return l.target === d;
                                            }).attr("x2", d.x).attr("y2", d.y);
                                        }));
                        circle.append("title").text(function(d){

                            return d.name;
                        });


                        var text = svg.append("g").selectAll("text").data(
                                force.nodes()).enter().append("text").attr(
                                "x", 8).attr("y", ".31em").text(
                                function(d) {
                                    return d.name;
                                });

                        //selection is happening 
                        var selected = circle.filter(function(d) {
                            return d.name;
                        });

                        selected.each(function(d) {
                            // d contains the data for the node and this is the circle element

                            console.log(d.name);
                        });


                          var drag = d3.behavior.drag()
                            .on("drag", function(d,i) {
                                d.x += d3.event.dx
                                d.y += d3.event.dy
                                d3.select(this).attr("transform", function(d,i){
                                    return "translate(" + d.x + "," + d.y + ")";
                                })
                            });

                        var circle = svg.append("g").selectAll("circle")
                                .data(force.nodes()).enter().append(
                                        "circle").attr("r", 6).on("click",
                                        clickfn).call(drag);

                        var clickfn = function(circle) {
                            alert();
                        }



                        // Use elliptical arc path segments to doubly-encode directionality.
                        function tick() {
                            path.attr("d", linkArc);
                            circle.attr("transform", transform);
                            text.attr("transform", transform);
                        }

                        function linkArc(d) {
                            var dx = d.target.x - d.source.x, dy = d.target.y
                                    - d.source.y, dr = Math.sqrt(dx * dx
                                    + dy * dy);
                            return "M" + d.source.x + "," + d.source.y
                                    + "A" + dr + "," + dr + " 0 0,1 "
                                    + d.target.x + "," + d.target.y;
                        }

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

</script>

这里有一个例子和一个类似的讨论@MohamedAliJamaoui你能看一看吗,我已经尝试了很多,所有的节点都在工作,我只需要箭头是你想要的。或者你可以为你拖动的节点设置
fixed
属性为
true
{"links":[{"source":"9804500485","target":"9804086391","type":"licensing"},{"source":"9804500485","target":"8420697490","type":"resolved"},{"source":"9804086391","target":"9804056963","type":"licensing"},{"source":"8420697490","target":"9804086391","type":"suit"},{"source":"9804086391","target":"9874525986","type":"licensing"},{"source":"9804500485","target":"9806895472","type":"resolved"},{"source":"8420697490","target":"9836444045","type":"licensing"},{"source":"9836444045","target":"9804500485","type":"licensing"},{"source":"9804500485","target":"9874525986","type":"licensing"},{"source":"9836444045","target":"9804086391","type":"suit"}]}