2017-02-27 4 views
0

Ich habe eine Anwendung von d3.js, wo ich Drag Bereich jedes Knotens durch Kreis/Rechteck begrenzen müssen. Dieser Ziehbereich kann für jeden Knoten statisch sein und kann in seinen json-Daten enthalten sein. Hier http://jsfiddle.net/InferOn/5wssqqdw/1/ Ich fand ein Beispiel, aber es erfüllt meine Anforderung nicht.Limit Drag Bereich jeden Knoten d3.js

Was ich will, wie folgt aus:

enter image description here

Hier mein Beispiel ist, wenn ich brauche dieses Zeug zu tun.

<!DOCTYPE html> 
 
<meta charset="utf-8"> 
 

 
<body> 
 
<script 
 
    src="https://code.jquery.com/jquery-3.1.1.min.js" 
 
    integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" 
 
    crossorigin="anonymous"></script> 
 
    <script src="http://d3js.org/d3.v3.min.js"></script> 
 
    <style> 
 
    body{ 
 
\t background:url(images/bg.jpg) repeat; 
 
} 
 
\t svg{ 
 
\t margin: 0 auto; 
 
\t display: block; 
 
} 
 
.link{ 
 
\t stroke: #51565b; 
 
\t stroke-width:20; \t 
 
\t stroke-opacity: 1; 
 
\t 
 
} 
 
    </style> 
 
    <script> 
 
    var width = 800, 
 
    height = 600 
 

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

 

 
var force = d3.layout.force() 
 
    .gravity(1) 
 
    .linkDistance(function (d) { 
 
    return d.distance; 
 
\t }) 
 
.charge(-40000) 
 
.size([width, height]); 
 

 
var datajson = { 
 
    "nodes": [{ 
 
    "name": "a", 
 
    "node_id": "10", 
 
    "group": 2, 
 
\t "node_img" : "http://loremflickr.com/320/240/dog" 
 
    }, { 
 
    "name": "b", 
 
    "group": 1, 
 
\t "node_id": "11", 
 
\t "node_img" : "http://loremflickr.com/320/240/dog" 
 
    }, { 
 
    "name": "c", 
 
    "group": 1, 
 
\t "node_id": "12", 
 
\t "node_img" : "http://loremflickr.com/320/240/dog" 
 
    } 
 
    ], 
 
    "links": [{ 
 
    "source": 0, 
 
    "target": 1, 
 
    "value": 1, 
 
    "distance": 400 
 
    }, { 
 
    "source": 1, 
 
    "target": 2, 
 
    "value": 2, 
 
    "distance": 300 
 
    }, { 
 
    "source": 2, 
 
    "target": 0, 
 
    "value": 3, 
 
    "distance": 300 
 
    }] 
 
} 
 

 
var numNodes = datajson.nodes.length 
 
var r = 20; 
 
datajson.nodes.forEach(function(node, i) { 
 
    node.x = width/2 + r * Math.sin(2 * Math.PI * i/numNodes) 
 
    node.y = height/2 + r * Math.cos(2 * Math.PI * i/numNodes) 
 
}) 
 

 
force 
 
    .nodes(datajson.nodes) 
 
    .links(datajson.links) 
 
    .start(); 
 

 
var drag = force.drag() 
 
    .on("drag", dblclick); 
 

 
var link = svg.selectAll(".link") 
 
    .data(datajson.links) 
 
    .enter().append("line") 
 
    .attr("class", "link"); 
 

 
var node = svg.selectAll(".node") 
 
    .data(datajson.nodes) 
 
    .enter().append("g") 
 
    .attr("class", function(d) { return "node "+"class_"+d.node_id}) 
 
    .call(force.drag); 
 

 
\t 
 
    \t //circle 
 
\t var circle = node.append("circle") 
 
\t .attr("r", 55) 
 
\t .attr("id", function(d) { return d.node_id }) 
 
\t .style("fill", function (d) { return 'rgba(81,86,91,1)'; }) 
 
\t .attr("class", function(d) { return "circle circle_"+d.node_id }); 
 
\t 
 
\t //image 
 
node.append("image") 
 
    .attr("x", -37) 
 
    .attr("y", -37) 
 
    .attr("width", 75) 
 
    .attr("height", 75) 
 
    .attr("xlink:href", function(d) { 
 
    return d.node_img; 
 
    }); 
 
    
 
force.on("tick", function() { 
 
    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; 
 
    }); 
 

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

 

 
function dblclick(d) { 
 

 
} 
 
    
 
    </script> 
 
</body>

Antwort

1

Hier ist ein Weg, dies zu tun:

<!DOCTYPE html> 
 
<meta charset="utf-8"> 
 

 
<body> 
 
    <script src="https://code.jquery.com/jquery-3.1.1.min.js" integrity="sha256-hVVnYaiADRTO2PzUGmuLJr8BLUSjGIZsDYGmIJLv2b8=" crossorigin="anonymous"></script> 
 
    <script src="http://d3js.org/d3.v3.min.js"></script> 
 
    <style> 
 
    body { 
 
     background: url(images/bg.jpg) repeat; 
 
    } 
 
    
 
    svg { 
 
     margin: 0 auto; 
 
     display: block; 
 
    } 
 
    
 
    .link { 
 
     stroke: #51565b; 
 
     stroke-width: 20; 
 
     stroke-opacity: 1; 
 
    } 
 
    </style> 
 
    <script> 
 
    var width = 800, 
 
     height = 600 
 

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

 
    var force = d3.layout.force() 
 
     .gravity(1) 
 
     .linkDistance(function(d) { 
 
     return d.distance; 
 
     }) 
 
     .charge(-40000) 
 
     .size([width, height]); 
 

 
    var datajson = { 
 
     "nodes": [{ 
 
     "name": "a", 
 
     "node_id": "10", 
 
     "group": 2, 
 
     "node_img": "http://loremflickr.com/320/240/dog", 
 
     "drag_radius": 150 
 
     }, { 
 
     "name": "b", 
 
     "group": 1, 
 
     "node_id": "11", 
 
     "node_img": "http://loremflickr.com/320/240/dog", 
 
     "drag_radius": 200 
 
     }, { 
 
     "name": "c", 
 
     "group": 1, 
 
     "node_id": "12", 
 
     "node_img": "http://loremflickr.com/320/240/dog", 
 
     "drag_radius": 100 
 
     }], 
 
     "links": [{ 
 
     "source": 0, 
 
     "target": 1, 
 
     "value": 1, 
 
     "distance": 400 
 
     }, { 
 
     "source": 1, 
 
     "target": 2, 
 
     "value": 2, 
 
     "distance": 300 
 
     }, { 
 
     "source": 2, 
 
     "target": 0, 
 
     "value": 3, 
 
     "distance": 300 
 
     }] 
 
    } 
 

 
    var numNodes = datajson.nodes.length 
 
    var r = 20; 
 
    datajson.nodes.forEach(function(node, i) { 
 
     node.x = width/2 + r * Math.sin(2 * Math.PI * i/numNodes) 
 
     node.y = height/2 + r * Math.cos(2 * Math.PI * i/numNodes) 
 
    }) 
 

 
    force 
 
     .nodes(datajson.nodes) 
 
     .links(datajson.links) 
 
     .start(); 
 

 
    var drag = force.drag() 
 
     .on("drag", drag) 
 
     .on("dragstart", dragstart) 
 
     .on("dragend", dragend); 
 

 
    var link = svg.selectAll(".link") 
 
     .data(datajson.links) 
 
     .enter().append("line") 
 
     .attr("class", "link"); 
 

 
    var node = svg.selectAll(".node") 
 
     .data(datajson.nodes) 
 
     .enter().append("g") 
 
     .attr("class", function(d) { 
 
     return "node " + "class_" + d.node_id 
 
     }) 
 
     .call(force.drag); 
 

 

 
    //circle 
 
    var circle = node.append("circle") 
 
     .attr("r", 55) 
 
     .attr("id", function(d) { 
 
     return d.node_id 
 
     }) 
 
     .style("fill", function(d) { 
 
     return 'rgba(81,86,91,1)'; 
 
     }) 
 
     .attr("class", function(d) { 
 
     return "circle circle_" + d.node_id 
 
     }); 
 

 
    //image 
 
    node.append("image") 
 
     .attr("x", -37) 
 
     .attr("y", -37) 
 
     .attr("width", 75) 
 
     .attr("height", 75) 
 
     .attr("xlink:href", function(d) { 
 
     return d.node_img; 
 
     }); 
 

 
    force.on("tick", function() { 
 
     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; 
 
     }); 
 

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

 
    function drag(d) { 
 
     var dx = d.orig_x - d.px 
 
      dy = d.orig_y - d.py, 
 
      dd = Math.sqrt((dx * dx) + (dy * dy)); 
 
     // am I out of bounds 
 
     if (dd >= d.drag_radius - 55){ 
 
     // set to previous values 
 
     d.px = d.last_x; 
 
     d.py = d.last_y; 
 
     } 
 
     // remember previous values 
 
     d.last_x = d.px; 
 
     d.last_y = d.py; 
 
    } 
 
    
 
    function dragstart(d) { 
 
     // original position 
 
     if (!d.orig_x) d.orig_x = d.x; 
 
     if (!d.orig_y) d.orig_y = d.y; 
 
    
 
     // draw bounds circle 
 
     d.bounds_obj = svg.append('circle') 
 
     .attr("transform", "translate(" + d.orig_x + "," + d.orig_y + ")") 
 
     .attr("r", d.drag_radius) 
 
     .style("fill", "none") 
 
     .style("stroke", "steelblue") 
 
     .style("stroke-width", "2px"); 
 
    } 
 
    function dragend(d) { 
 
     // remove circle and clean-up 
 
     d.bounds_obj.remove(); 
 
     d.bounds_obj = undefined; 
 
    } 
 
    </script> 
 
</body>

+0

Hallo, es wie erwartet mit einer Ausnahme arbeitet, Kreis der Grenzbereich entlang bewegt mit jeder Knoten, kann es (äußerer Kreis) festgelegt werden, damit Knotenposition nicht während des Ziehens geändert werden kann. BTW danke für die Hilfe :) – Subrata

+0

@Subrata, meinst du, dass nach jedem Ziehen der Begrenzungskreis die neue Position des Knotens umgibt? – Mark

+0

Ja @Mark, der Begrenzungskreis. – Subrata

Verwandte Themen