import { Node } from './graph-data.js' import * as d3 from 'd3' import { class2color, class2darkenColor } from './utils.js' export function appendNodeToGraph( svgNodes: d3.Selection, // 타입 지정 nodes: Node[], options: any ) { const nodeEnter = svgNodes .selectAll('.node') .data(nodes, d => d.id) .enter() .append('g') .attr('class', d => { let classes = 'node' if (d.icon) classes += ' node-icon' if (d.image) classes += ' node-image' if (options.highlight) { options.highlight.forEach((highlight: any) => { if (d.labels[0] === highlight.class && d.properties[highlight.property] === highlight.value) { classes += ' node-highlighted' } }) } return classes }) .call( d3 .drag() // 제네릭 타입 지정 .on('start', (event, d) => dragStarted(event, d, options.simulation)) .on('drag', (event, d) => dragged(event, d)) .on('end', (event, d) => dragEnded(event, d, options.simulation)) ) nodeEnter .append('circle') .attr('r', options.nodeRadius) .style('fill', d => class2color(options.classes2colors, d.labels[0], options.colors, options.numClasses)) .style('stroke', d => class2darkenColor(class2color(options.classes2colors, d.labels[0], options.colors, options.numClasses)) ) .style('stroke-width', 2) nodeEnter .append('text') .attr('dy', 4) .attr('text-anchor', 'middle') .text(d => d.properties.name || d.id) return nodeEnter } function dragStarted( event: d3.D3DragEvent, d: Node, simulation: d3.Simulation ) { if (!event.active) simulation.alphaTarget(0.3).restart() d.fx = d.x d.fy = d.y } function dragged(event: d3.D3DragEvent, d: Node) { d.fx = event.x d.fy = event.y } function dragEnded(event: d3.D3DragEvent, d: Node, simulation: d3.Simulation) { if (!event.active) simulation.alphaTarget(0) d.fx = null d.fy = null }