【发布时间】:2015-10-12 23:25:48
【问题描述】:
具有如下设置的图集力图,我想从绘图区域中的任何位置放大和缩小鼠标滚轮事件,但节点(圆圈)以允许拖动单个节点。
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 + ")"; });
});
我对这段代码的问题是单击一个节点并拖动它会拖动整个图形,而当删除 call(... redraw) 部分时,它会让我拖动单个节点。
有没有办法混合这两种行为,或者在指针位于节点内时防止缩放,或者在全局 (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>
【问题讨论】:
-
您是否尝试过在单个节点的拖动处理程序中停止事件传播?
-
你读过this answer吗?
-
Jap 应该是@Cool Blue 关于我的主题的答案的混合体。请创建一个小提琴。在那里实现它应该非常容易和快速=)
-
@Cool Blue,感谢您指出这一点,但是我不确定发生了什么。我会尽快创建一个 Fiddle。
-
功能小提琴在这里:jsfiddle.net/pducrot/omb470vw/2