/* prettier-ignore */ d3.select('body') .append('canvas') .attr('width', 960) .attr('height', 500); const canvas = d3.select('canvas') const context = canvas.node().getContext('2d') const width = canvas.property('width') const height = canvas.property('height') // make a rect for the background // d3.drag updates these values behind the scenes const background = { x: 0, y: 0, x2: 0, y2: 0 } const radius = 10 // // setup force simulation // const graph = { nodes: [ { id: 0, size: 10 }, { id: 1, size: 5 }, { id: 2, size: 2 }, { id: 3, size: 3 }, { id: 4, size: 30 }, { id: 5, size: 40 } ], links: [ { source: 0, target: 1 }, { source: 0, target: 2 }, { source: 1, target: 0 }, { source: 3, target: 0 }, { source: 4, target: 1 } ] } const simulation = d3 .forceSimulation() .force('link', d3.forceLink().id(d => d.id)) .force('charge', d3.forceManyBody()) .force('center', d3.forceCenter(width / 2, height / 2)) simulation.nodes(graph.nodes).on('tick', ticked) function ticked() { render() } // // // render() canvas.call( d3 .drag() .subject(dragSubject) .on('start', dragStarted) .on('drag', dragged) .on('end', dragEnded) .on('start.render drag.render end.render', render) ) function render() { context.clearRect(0, 0, width, height) context.clearRect(0, 0, width, height) // draw a line for each link context.strokeStyle = '#aaa' context.lineWidth = 1 context.beginPath() graph.links.forEach(link => { context.moveTo( graph.nodes[link.source].x + background.x, graph.nodes[link.source].y + background.y ) context.lineTo( graph.nodes[link.target].x + background.x, graph.nodes[link.target].y + background.y ) context.stroke() // draw a circle for each node context.beginPath() graph.nodes.forEach(node => { context.moveTo(node.x + background.x + radius, node.y + background.y) context.arc( node.x + background.x, node.y + background.y, radius, 0, 2 * Math.PI ) }) context.fillStyle = 'red' context.fill() }) } function dragSubject() { let i const n = graph.nodes.length let dx let dy let d2 let s2 = radius * radius * 4 let node let subject for (i = 0; i < n; i += 1) { node = graph.nodes[i] console.log('node from dragSubject', node) dx = d3.event.x - node.x - background.x dy = d3.event.y - node.y - background.y d2 = dx * dx + dy * dy console.log('dx', dx) console.log('dy', dy) console.log('d2', d2) console.log('s2', s2) if (d2 < s2) { subject = node s2 = d2 } else if (typeof subject === 'undefined') { subject = background console.log('background', background) } } return subject } function dragStarted() { // if (!d3.event.active) simulation.alphaTarget(0.3).restart(); // circles.splice(circles.indexOf(d3.event.subject), 1); // circles.push(d3.event.subject); d3.event.subject.active = true } function dragged() { d3.event.subject.x = d3.event.x d3.event.subject.y = d3.event.y } function dragEnded() { d3.event.subject.active = false }