3d-force-graph icon indicating copy to clipboard operation
3d-force-graph copied to clipboard

SVG and Text In Nodes

Open kennetpostigo opened this issue 4 years ago • 2 comments

Is your feature request related to a problem? Please describe. Hi, i'd really love to ability to easily add svg and text inside of node spheres. I don't know webGL or threejs but was wondering if this functionality was available or could be added by a function accessor

Describe the solution you'd like For Text in nodes

.nodeTextContent(node => node.textContent)

This would render text inside of a node sphere

For SVG in nodes

.nodeSvgIcon(node => node.icon)

this would render an icon in the node sphere

Using both would look like

  1. Graph renders svg icon and then text
Graph
.nodeSvgIcon(node => node.icon)
.nodeTextContent(node => node.textContent)
  1. Graph render text then svg icon
Graph
.nodeTextContent(node => node.textContent)
.nodeSvgIcon(node => node.icon)

Describe alternatives you've considered I've tried to manually use three-spritetext but the sphere would hide text if it wasn't set to transparent no matter what the opacity and the text wouldn't fit in the sphere

kennetpostigo avatar Mar 20 '20 18:03 kennetpostigo

Text fitting in the sphere would be difficult, as the text size would have to get small enough to fit or the sphere would need to grow, and the amount of text could also vary. Text under or over the node would be best practice. This would also fix the problem with spheres needing to be transparent.

If you want to use icons, it is best to not even use the spheres any longer. He has an example of images used for nodes here: https://vasturiano.github.io/3d-force-graph/example/img-nodes/ Code: https://github.com/vasturiano/3d-force-graph/blob/master/example/img-nodes/index.html

In my use case the text and image would become misaligned when moving the camera, so I just created a canvas, added whatever I wanted to make the node look how I wanted, then turned it into a sprite.

const generateNodeThreeObject = node => {
  canvas = document.createElement('canvas');
  const context = canvas.getContext('2d');
  // add image, text etc
  const texture = new THREE.Texture(context.canvas);
  texture.needsUpdate = true;
  const material = new THREE.SpriteMaterial({ map: texture });
  const sprite = new THREE.Sprite(material);
  sprite.scale.set(32, 32, 1);
  return sprite;
}

// include this method in forceGraph3D call
graph
  .graphData(data)
  ...
  .nodeThreeObject(generateNodeThreeObject)
  ...

If you are reloading your graph a lot you may want to create a canvas cache to use inside of that function to save memory.

Alexithemia avatar Apr 07 '20 16:04 Alexithemia

Is there any solution to this?

Spenhouet avatar Mar 16 '23 22:03 Spenhouet