简体   繁体   English

如何将d3.js中的节点拖到javascript中?

[英]How to drag nodes in d3.js in javascript?

Following is the code for making a force directed graph using d3.js:以下是使用 d3.js 制作力导向图的代码:

How can I make dragging a node only when you drag a node ?如何使仅在拖动节点时才拖动节点

Cause currently when you drag anywhere over the stage some nearby node get dragged.目前,当您在舞台上的任何地方拖动时,一些附近的节点会被拖动。 Instead, how can I constrain the drag to occur only if I'm dragging a real node (rather than the surrounding area)相反,如何才能限制拖动仅在拖动真实节点(而不是周围区域)时发生

Also how can I make the stage zoomable & draggable?另外,如何使舞台可缩放和可拖动?

 const graph = { nodes: [{ name: 'john', age: 35 }, { name: 'simon', age: 37 }, { name: 'manjoor', age: 35 }, { name: 'lorg', age: 34 }, { name: 'kilvin', age: 32 }, ], links: [{ source: 'john', target: 'simon' }, { source: 'john', target: 'manjoor' }, { source: 'simon', target: 'lorg' }, { source: 'simon', target: 'kilvin' }, { source: 'manjoor', target: 'kilvin' }, { source: 'lorg', target: 'john' }, { source: 'lorg', target: 'manjoor' }, { source: 'kilvin', target: 'manjoor' }, ] } const canvas = d3.select('.network') const width = canvas.attr('width') const height = canvas.attr('height') const r = 30 const ctx = canvas.node().getContext('2d') const color = d3.scaleOrdinal(d3.schemeAccent); const simulation = d3.forceSimulation().force('x', d3.forceX(width / 2)).force('y', d3.forceY(height / 2)).force('collide', d3.forceCollide(r + 20)).force('charge', d3.forceManyBody().strength(-100)).force('link', d3.forceLink().id(node => node.name)).on('tick', update) simulation.nodes(graph.nodes) simulation.force('link').links(graph.links) canvas.call(d3.drag().container(canvas.node()).subject(dragsubject).on('start', dragstarted).on('drag', dragged).on('end', dragended) ) function update() { ctx.clearRect(0, 0, width, height) ctx.beginPath() ctx.globalAlpha = 0.5 ctx.strokeStyle = 'blue' graph.links.forEach(drawLink) ctx.stroke() ctx.beginPath() ctx.globalAlpha = 1 graph.nodes.forEach(drawNode) ctx.fill() } function dragsubject(event) { return simulation.find(event.x, event.y); } function drawNode(d) { ctx.fillStyle = color(d.party) ctx.moveTo(dx, dy) ctx.arc(dx, dy, r, 0, Math.PI * 2) } function drawLink(l) { ctx.moveTo(l.source.x, l.source.y) ctx.lineTo(l.target.x, l.target.y) } function dragstarted(event) { if (.event.active) simulation.alphaTarget(0.3);restart(). event.subject.fx = event.subject;x. event.subject.fy = event.subject;y. } function dragged(event) { event.subject.fx = event;x. event.subject.fy = event;y. } function dragended(event) { if (.event;active) simulation.alphaTarget(0). event;subject.fx = null. event;subject.fy = null; } update()
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.js"></script> <canvas id=.network" width="600" height="300"></canvas>

From the documentation :文档中:

simulation.find(x, y[, radius]) - Returns the node closest to the position ⟨x,y⟩ with the given search radius. simulation.find(x, y[, radius]) - 返回最接近具有给定搜索半径的 position ⟨x,y⟩ 的节点。 If radius is not specified, it defaults to infinity.如果未指定半径,则默认为无穷大。 If there is no node within the search area, returns undefined.如果搜索区域内没有节点,则返回 undefined。

Passing a radius of r - which is the same as the ball radius - made it possible to only register dragging when the action is r from the centre of the node.传递r的半径(与球的半径相同)使得仅当动作距离节点中心为r时才可以注册拖动。

 const graph = { nodes: [{ name: 'john', age: 35 }, { name: 'simon', age: 37 }, { name: 'manjoor', age: 35 }, { name: 'lorg', age: 34 }, { name: 'kilvin', age: 32 }, ], links: [{ source: 'john', target: 'simon' }, { source: 'john', target: 'manjoor' }, { source: 'simon', target: 'lorg' }, { source: 'simon', target: 'kilvin' }, { source: 'manjoor', target: 'kilvin' }, { source: 'lorg', target: 'john' }, { source: 'lorg', target: 'manjoor' }, { source: 'kilvin', target: 'manjoor' }, ] } const canvas = d3.select('.network') const width = canvas.attr('width') const height = canvas.attr('height') const r = 30 const ctx = canvas.node().getContext('2d') const color = d3.scaleOrdinal(d3.schemeAccent); const simulation = d3.forceSimulation().force('x', d3.forceX(width / 2)).force('y', d3.forceY(height / 2)).force('collide', d3.forceCollide(r + 20)).force('charge', d3.forceManyBody().strength(-100)).force('link', d3.forceLink().id(node => node.name)).on('tick', update) simulation.nodes(graph.nodes) simulation.force('link').links(graph.links) canvas.call(d3.drag().container(canvas.node()).subject(dragsubject).on('start', dragstarted).on('drag', dragged).on('end', dragended) ) function update() { ctx.clearRect(0, 0, width, height) ctx.beginPath() ctx.globalAlpha = 0.5 ctx.strokeStyle = 'blue' graph.links.forEach(drawLink) ctx.stroke() ctx.beginPath() ctx.globalAlpha = 1 graph.nodes.forEach(drawNode) ctx.fill() } function dragsubject(event) { return simulation.find(event.x, event.y, r); } function drawNode(d) { ctx.fillStyle = color(d.party) ctx.moveTo(dx, dy) ctx.arc(dx, dy, r, 0, Math.PI * 2) } function drawLink(l) { ctx.moveTo(l.source.x, l.source.y) ctx.lineTo(l.target.x, l.target.y) } function dragstarted(event) { if (.event.active) simulation.alphaTarget(0.3);restart(). event.subject.fx = event.subject;x. event.subject.fy = event.subject;y. } function dragged(event) { event.subject.fx = event;x. event.subject.fy = event;y. } function dragended(event) { if (.event;active) simulation.alphaTarget(0). event;subject.fx = null. event;subject.fy = null; } update()
 <script src="https://cdnjs.cloudflare.com/ajax/libs/d3/6.2.0/d3.js"></script> <canvas id=.network" width="600" height="300"></canvas>

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM