({ node }: { node: GraphNode })
| 97 | } |
| 98 | |
| 99 | function NodeLabelSprite({ node }: { node: GraphNode }) { |
| 100 | const label = useMemo( |
| 101 | () => createLabelTexture(node.name, node.color), |
| 102 | [node.name, node.color], |
| 103 | ); |
| 104 | |
| 105 | useEffect(() => { |
| 106 | return () => label?.texture.dispose(); |
| 107 | }, [label]); |
| 108 | |
| 109 | if (!label) return null; |
| 110 | |
| 111 | const worldFontSize = Math.max(1.8, node.size * 0.4); |
| 112 | const worldHeight = worldFontSize * (label.height / TEXTURE_FONT_SIZE); |
| 113 | const worldWidth = worldHeight * (label.width / label.height); |
| 114 | |
| 115 | return ( |
| 116 | <sprite |
| 117 | position={[node.x, node.y + node.size * 0.7 + worldHeight / 2, node.z]} |
| 118 | scale={[worldWidth, worldHeight, 1]} |
| 119 | renderOrder={20} |
| 120 | frustumCulled={false} |
| 121 | > |
| 122 | <spriteMaterial |
| 123 | map={label.texture} |
| 124 | transparent |
| 125 | depthWrite={false} |
| 126 | toneMapped={false} |
| 127 | /> |
| 128 | </sprite> |
| 129 | ); |
| 130 | } |
| 131 | |
| 132 | export function NodeLabels({ |
| 133 | nodes, |
nothing calls this directly
no test coverage detected