javascript - 如何在javascript中的d3.js中获取拖动事件?
问题描述
以下是使用 d3.js 在 javascript 中绘制力有向图的代码
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(d3.event.x, d3.event.y)
}
function drawNode(d) {
ctx.fillStyle = color(d.party)
ctx.moveTo(d.x, d.y)
ctx.arc(d.x, d.y, 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>
我正在画布上获取图表。
但是我收到以下错误:
&当我调试时,我可以看到这是发生错误的地方 return simulation.find(d3.event.x, d3.event.y)
......似乎缺少事件......有没有办法解决这个问题。这发生在拖动...&所以拖动每个节点都不起作用。
或者有人可以建议一种拖动节点的方法......
解决方案
您使用的是 d3 版本 6。d3.event
已被删除。请仔细阅读更改日志,降级您的 d3 版本,或查找更多最新示例。
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(d.x, d.y)
ctx.arc(d.x, d.y, 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>
推荐阅读
- oracle - 使用 oracle 在 docker 中运行 flyway 迁移
- redis - Redis.blPop:如何检查有多少进程等待'key'?
- r - R-Project:如何限制 SPI 图中的轴?ylim 和 xlim 不起作用
- selenium - appium android本机应用程序测试中的此会话错误不支持“css选择器”-Java
- electron - 错误:fs.readFileSync 不是使用 Electron 的函数
- java - 尝试从 ArrayList 获取字符串时出现 IndexOutOfBoundsException
- node.js - 使用全球 AuthGuard 自定义护照策略
- django-viewflow - 如何完成所有并行活动 ViewFlow (Terminate End)?
- forms - c ++如何将标签动态添加到组框并设置其位置
- python-3.x - Python:通过 COM 与 Lotus Domino 连接