我使用D3.v4和画布进行了大型力布局。因为我不能真正使用SVG。
如何为画布上的元素制作工具提示?
至少,如何识别鼠标在画布上的位置?
我尝试使用this问题的答案作为灵感,检查鼠标光标在画布上的位置,然后使用simulation.find(x,y,radius)
识别附近的节点。但是,这会导致很多误报,我感觉HTML事件和simulation.find()
的工作方式不同和/或使用不同的坐标标准。
有没有人对此有任何想法或解决方案?
修改:建议您查看this问题。我试图这样做,它有点工作。现在的问题是,正如所怀疑的,simulation.find(..)
似乎没有使用这些画布坐标来查找网络中的节点。
对于好奇,这是我用来查找光标和附近节点的当前函数:
canvas = d3.select('canvas')
function getPos(e) {
rect = canvas.node().getBoundingClientRect();
scaleX = width / rect.width;
scaleY = height / rect.height;
x = (e.clientX - rect.left);
y = (e.clientY - rect.top);
node = simulation.find(x,y, 3);
return {
x : x,
y : y,
node : node
};
}
答案 0 :(得分:1)
您应该使用内置的d3.mouse来确定画布中的位置:
d3.select("canvas").on("mousemove", function(d){
var p = d3.mouse(this);
var node = simulation.find(p[0], p[1]);
});
这是一个快速示例,它突出显示最靠近鼠标位置的节点:
<!DOCTYPE html>
<meta charset="utf-8">
<canvas width="960" height="600"></canvas>
<script src="https://d3js.org/d3.v4.min.js"></script>
<script>
var canvas = document.querySelector("canvas"),
context = canvas.getContext("2d"),
width = canvas.width,
height = canvas.height;
var simulation = d3.forceSimulation()
.force("link", d3.forceLink().id(function(d) {
return d.id;
}))
.force("charge", d3.forceManyBody())
.force("center", d3.forceCenter(width / 2, height / 2));
var graph = {};
graph.nodes = d3.range(100).map(function(d) {
return {
id: d
}
});
graph.links = d3.range(200).map(function(d) {
return {
source: Math.floor(Math.random() * 100),
target: Math.floor(Math.random() * 100)
};
});
simulation
.nodes(graph.nodes)
.on("tick", ticked);
simulation.force("link")
.links(graph.links);
function ticked() {
context.clearRect(0, 0, width, height);
context.beginPath();
graph.links.forEach(drawLink);
context.strokeStyle = "#aaa";
context.stroke();
context.beginPath();
graph.nodes.forEach(drawNode);
context.fill();
context.strokeStyle = "#fff";
context.stroke();
if (closeNode) {
context.beginPath();
drawNode(closeNode)
context.fill();
context.strokeStyle = "#ff0000";
context.stroke();
}
}
var closeNode;
d3.select("canvas").on("mousemove", function(d){
var p = d3.mouse(this);
closeNode = simulation.find(p[0], p[1]);
ticked();
})
function drawLink(d) {
context.moveTo(d.source.x, d.source.y);
context.lineTo(d.target.x, d.target.y);
}
function drawNode(d) {
context.moveTo(d.x + 3, d.y);
context.arc(d.x, d.y, 3, 0, 2 * Math.PI);
}
</script>
&#13;