使用如下设置的图集力图,我想放大和缩小绘图区域中任何位置的鼠标滚轮事件,但是节点(圆圈)以便允许拖动单个节点。
var svg = graph.append("svg")
.attr("width", width)
.attr("height", height)
.attr("pointer-events", "all")
.call(d3.behavior.zoom().on("zoom", redraw))
.append('g');
var link = svg.selectAll(".link")
.data(links)
.enter().append("line")
.attr("class", "link")
var node = svg.selectAll(".node")
.data(nodes)
.enter().append("svg:g")
.attr("class", "node")
.on("dblclick", dblclick)
.call(force.drag);
node.append("circle")
.attr("class", "circle");
function redraw() {
svg.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")");
}
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 + ")"; });
});
我对此代码的问题是单击节点并拖动它会拖动整个图形,而当删除调用(...重绘)部分时,它会让我拖动单个节点。
有没有办法混合两种行为,当指针在节点内时阻止缩放,或者在全局(svg)事件中有节点事件普遍存在?
<!DOCTYPE html>
<html>
<head>
<title>Fidlde</title>
<script type="text/javascript" src="d3-master/d3.v3.min.js"></script>
<style>
.circle {
fill: #F5F5F5;
stroke: #999999;
stroke-width: 3;
}
.node text {
pointer-events: none;
font: 10px sans-serif;
}
.link {
stroke: #999999;
stroke-opacity: .6;
stroke-width: 3;
}
</style>
</head>
<body>
<div id="graph">Hello!</div>
<script>
// graph size
var width = 400;
var height = 400;
var nodes = [{name: 'A'}, {name: 'B'}, {name: 'C'}, {name: 'D'}];
var edges = [{source: 'A', target: 'B'}, {source: 'B', target: 'C'}, {source: 'C', target: 'A'}, {source: 'C', target: 'D'}];
var nodeMap = {};
nodes.forEach(function(x) { nodeMap[x.name] = x; });
var links = edges.map(function(x) {
return { source: nodeMap[x.source], target: nodeMap[x.target], value: 1 };
});
var graph = d3.select("#graph");
var svg = graph.append("svg")
.attr("width", width)
.attr("height", height)
.attr("pointer-events", "all")
.call(d3.behavior.zoom().on("zoom", redraw))
.append('g');
var force = d3.layout.force()
.gravity(.25)
.distance(140)
.charge(-3500)
.size([width, height]);
/* Issue was here, the following code addresses it.
Thanks to Lars and Cool Blue - see comments
var drag = force.drag()
.on("dragstart", dragstart);
*/
var stdDragStart = force.drag().on("dragstart.force");
force.drag()
.on("dragstart", function(d){
//prevent dragging on the nodes from dragging the canvas
d3.event.sourceEvent.stopPropagation();
stdDragStart.call(this, d);
});
force
.nodes(nodes)
.links(links)
.friction(0.8)
.start();
var link = svg.selectAll(".link")
.data(links)
.enter().append("line")
.attr("class", "link");
var node = svg.selectAll(".node")
.data(nodes)
.enter().append("svg:g")
.attr("class", "node")
.on("dblclick", dblclick)
.call(force.drag);
node.append("circle")
.attr("class", "circle")
.attr("r", 10);
node.append("text")
.attr("dx", -4)
.attr("dy", ".35em")
.text(function(d) { return d.name; });
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 + ")"; });
});
// redraw after zooming
function redraw() {
svg.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")");
}
function dblclick(d) {
d3.select(this).classed("fixed", d.fixed = false);
}
function dragstart(d) {
d3.select(this).classed("fixed", d.fixed = true);
}
</script>
</body>
</html>
答案 0 :(得分:0)
In oder to address the remaining dragging node issue, I made the following changes in the code:
node.enter()
.append("svg:g")
.attr("pointer-events", "all")
.attr("id", function(d) { return '_'+d.name })
.attr("class", "node")
.on("click", nodeClick)
.on("dblclick", nodeDoubleClick)
.on("mouseover", nodeMouseOver)
.on("mouseout", nodeMouseOut)
.call(force.drag);
function nodeClick(d) {
// fix the current node to its position
d.fixed = true;
}
function nodeDoubleClick(d) {
// release the current node
d.fixed = false;
}
function nodeMouseOver(d) {
// move the current node to front - some nodes are overlapping each others
var sel = d3.select(this);
sel.moveToFront();
// stop the whole graph
force.stop();
}
function nodeMouseOut(d) {
// resume node motion
force.start();
}
I also removed the following dragstart function which remained from previous code and was probably called while zooming.
/* function dragstart(d) {
d3.select(this).classed("fixed", d.fixed = true);
}
*/
Everything is now properly working. Thank you all for your contributions.
答案 1 :(得分:-1)
尝试这段代码:)也可以
var width=600;
var height=600;
var nodes=[{
"name":"n1"
},{
"name":"n2"
},{
"name":"n3"
},{
"name":"n4"
},{
"name":"n5"
}];
var links=[{"source":0,"target":1},
{"source":0,"target":2},
{"source":0,"target":3},
{"source":1,"target":4},
{"source":2,"target":4},
{"source":3,"target":2}];
var svg = d3.select("body").append("svg")
.attr("width", width)
.attr("height", height)
.attr("transform","translate(200,200)");
svg.append("rect")
.attr("width",width)
.attr("height",height)
.attr("fill","none")
.attr("pointer-events","all")
.call(d3.behavior.zoom().on("zoom", redraw));;
var force=d3.layout.force().charge(-400).linkDistance(200);
force.nodes(nodes).links(links).start();
var link = svg.selectAll(".link")
.data(links)
.enter().append("line")
.attr("class", "link")
var node = svg.selectAll("circle")
.data(nodes)
.enter()
.append("circle")
.attr("class","circle")
.call(force.drag);
function redraw() {
svg.attr("transform", "translate(" + d3.event.translate + ")" + " scale(" + d3.event.scale + ")");
}
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 + ")"; });
});