/* 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'); const circles = [{ x: 50, y: 60, radius: 10 }, { x: 100, y: 80, radius: 10 }]; const rects = [{ x: 10, y: 10, x2: 210, y2: 210 }]; 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); // draw the black rectangle rects.forEach(rect => { context.fillStyle = 'black'; context.clearRect(0, 0, width, height); context.fillRect(rect.x, rect.y, rect.x2, rect.y2); // 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 + rect.x, graph.nodes[link.source].y + rect.y ); context.lineTo( graph.nodes[link.target].x + rect.x, graph.nodes[link.target].y + rect.y ); }); context.stroke(); // draw a circle for each node context.beginPath(); graph.nodes.forEach(node => { context.moveTo(node.x + rect.x + radius, node.y + rect.y); context.arc(node.x + rect.x, node.y + rect.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 - rects[0].x; dy = d3.event.y - node.y - rects[0].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') { rect = rects[0]; subject = rect; } } 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; }