Code Monkey home page Code Monkey logo

Comments (8)

longlp-sosene avatar longlp-sosene commented on July 20, 2024 1

Just work around and solve my problem with inject the callback function to handle increase fontsize (base on distance between Node and Camera) with control change event

Graph.controls()
    .addEventListener('change', ev => {
        handleChangeTextFormat()
    });

function getNodeDistanceWithCamera(node) {
    // get the position of the node
    // @ts-ignore
    const obj = node;
    if (!obj.x || !obj.y || !obj.z) return 0;
    const nodePosition = new THREE.Vector3(obj.x, obj.y, obj.z);
    // then get the distance between the node and camera , console.log it
    return nodePosition.distanceTo(Graph.cameraPosition())
}

function handleChangeTextFormat() {
    Graph.nodeThreeObject(node => {
        // console.log('handling text format');
        let label = node.label
        let distance = getNodeDistanceWithCamera(node) ?? 1;
        let fontSize = controls['Font size'] + highlight;
        let labelFontSize= fontSize + (2000 / distance)
        const nodeEl = document.createElement('div');
        nodeEl.textContent = label;
        nodeEl.className = 'node-label';
        nodeEl.style.fontSize = labelFontSize + 'px;
        return new CSS2DObject(nodeEl);
    })
}

from 3d-force-graph.

EncompassingResidential avatar EncompassingResidential commented on July 20, 2024

Hi @longlp , I got sprites to work in my React app. Here is my code. down below that I'll show the HTML code that I can not get to work if you can help.

Sprites / canvas code : TreeForceGraphComponent.js

import React, { useEffect } from 'react';
import ForceGraph3D from 'react-force-graph-3d';
import { Group, Mesh, MeshBasicMaterial, SphereGeometry, Sprite, SpriteMaterial, Texture } from 'three';

-function TreeForceGraphComponent({ tree_18_GraphData, targetBAGName, areNodeLabelsOn }) {

function createTextSprite(text) {
  const canvas = document.createElement('canvas');
  const context = canvas.getContext('2d');

  canvas.width = 512; 
  canvas.height = 256;
  context.font = '24px Arial';
  context.fillStyle = 'rgba(255, 255, 255, 1.0)';

  context.textAlign = 'left';
  context.textBaseline = 'middle';
  
  context.fillText(text, canvas.width / 2, canvas.height / 2);

  const texture = new Texture(canvas);
  texture.needsUpdate = true;

  const spriteMaterial = new SpriteMaterial({ map: texture });
  const sprite = new Sprite(spriteMaterial);

  sprite.scale.set(75, 75, 1);

  return sprite;
}

const nodeThreeObject = areNodeLabelsOn ? node => {

const group = new Group();

const nodeGeometry = new SphereGeometry(7);
const nodeMaterial = new MeshBasicMaterial({ color: node.color });
const mesh = new Mesh(nodeGeometry, nodeMaterial);
group.add(mesh);

const sprite = createTextSprite(node.id);
sprite.color = node.color;
sprite.textHeight = 1;
sprite.position.x = 0;
sprite.position.y = 0;
sprite.position.z = 8;
return sprite;

} : null;

 return (
    <div>
    <ForceGraph3D
        graphData={tree_18_GraphData}
        width={1000}
        height={500}
        backgroundColor="#B4B5C5"
        nodeThreeObject={ areNodeLabelsOn ? nodeThreeObject : undefined }
        nodeThreeObjectExtend={true}
        nodeLabel={nodes => `${nodes.id || 'SomE ThinG'} :: ${nodes.description || 'Empty Description'}`}
        nodeAutoColorBy="group"
        linkDirectionalParticles={6}
        linkWidth={3}
        linkOpacity={0.5}
        />
    </div>
);

}

export default TreeForceGraphComponent;

Here is React code trying to add HTML on each node, but not working: TreeForceGraphComponent.js

import React, { useCallback, useEffect, useRef } from 'react';

import ForceGraph3D from 'react-force-graph-3d';
import { CSS2DRenderer, CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer.js';
import { logEntry } from './Utilities';

function TreeForceGraphComponent({ tree_18_GraphData, targetBAGName, areNodeLabelsOn, focusNodeId }) {

const fgRef = useRef();

const nodeThreeObject = areNodeLabelsOn ? node => {

const nodeEl = document.createElement('div');
nodeEl.textContent = node.id;
nodeEl.style.color = node.color;
nodeEl.className = 'node-label';
const label = new CSS2DObject(nodeEl);

label.position.setY(5);

return label;

};

useEffect(() => {
const css2DRenderer = new CSS2DRenderer();

document.body.appendChild(css2DRenderer.domElement);

// Set the size of the CSS2DRenderer to match your graph container
// This might be dynamic depending on your setup
css2DRenderer.setSize(window.innerWidth, window.innerHeight);

// Update ForceGraph3D to use the CSS2DRenderer
if (fgRef.current) {
  fgRef.current.renderer([css2DRenderer]);
}

}, []);

const nodeAutoColorBy = (node) => {
if (node.id === targetBAGName) {
return 12;
}
return node.group;
};

const linkColorDetermine = link => {
if (link.type === 'Past Member') {
return 'green';
} else if (link.type === 'Current Member') {
return 'darkgreen';
} else if (link.type === 'Genre') {
return 'lightgreen';
} else if (link.type === 'Label') {
return 'blue';
} else {
return 'gray';
}
}

return (


<ForceGraph3D
graphData={tree_18_GraphData}
ref={fgRef}
onNodeDragStart={node => logEntry('TreeForceGraphComponent', onNodeDragStart: ${node.id}) }
onNodeDragEnd={node => logEntry('TreeForceGraphComponent', onNodeDragEnd: ${node.id}) }
onNodeClick={handleNodeClick}
width={1000}
height={500}
backgroundColor="#B4B5C5"
nodeAutoColorBy={nodeAutoColorBy}
nodeThreeObject={areNodeLabelsOn ? nodeThreeObject : undefined }
nodeThreeObjectExtend={true} // false turns off nodes with nodeThreeObject
linkWidth={areNodeLabelsOn ? 2 : 1}
linkOpacity={areNodeLabelsOn ? 0.5 : 0.4}
linkColor={linkColorDetermine}
linkDirectionalParticles={6}
nodeLabel={nodes => ${nodes.id || 'SomE ThinG'} :: ${nodes.description || 'Empty Description'}}
/>

);
}

export default TreeForceGraphComponent;

from 3d-force-graph.

EncompassingResidential avatar EncompassingResidential commented on July 20, 2024

Thank you Le Phi for replying. I got some un-referenced variables compiler errors:

import { CSS2DRenderer, CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer.js';

// Is your Graph variable this:
const Graph = useRef();
// If not this then I need your Graph declaration / definition.

// I have this three library import, but you are referencing a THREE.Vector3()
// what is your THREE definition?
import { Group, Mesh, MeshBasicMaterial, SphereGeometry, Sprite, SpriteMaterial, Texture } from 'three';

// What is your highlight variable defined as ?
let fontSize = controls['Font size'] + highlight;

from 3d-force-graph.

EncompassingResidential avatar EncompassingResidential commented on July 20, 2024

Le, I figured it out how to show labels all the time. I don't need this HTML specific solution. Since I got this to work I'm not sure what advantage the HTML path is?

The clue was in https://github.com/vasturiano/3d-force-graph/blob/master/example/text-nodes/index.html

I needed to
1 - npm install three-spritetext
2 - import
import SpriteText from 'three-spritetext';

so all I needed was:

import React, { useCallback, useEffect, useRef } from 'react';
import ForceGraph3D from 'react-force-graph-3d';
import SpriteText from 'three-spritetext';

const fgRef = useRef();

const nodeThreeObject = areNodeLabelsOn ? node => {

const sprite = new SpriteText(node.id);
sprite.color = node.color;
sprite.textHeight = 8;
sprite.position.x = 0;
sprite.position.y = 0;
sprite.position.z = 8;
return sprite;

} : null;

return (


<ForceGraph3D
graphData={tree_18_GraphData}
ref={fgRef}
onNodeDragStart={node => logEntry('TreeForceGraphComponent', onNodeDragStart: ${node.id}) }
onNodeDragEnd={node => logEntry('TreeForceGraphComponent', onNodeDragEnd: ${node.id}) }
onNodeClick={handleNodeClick}
width={1000}
height={500}
backgroundColor="#B4B5C5"
nodeAutoColorBy={nodeAutoColorBy}
nodeThreeObject={areNodeLabelsOn ? nodeThreeObject : undefined }
nodeThreeObjectExtend={true} // false turns off nodes with nodeThreeObject
linkWidth={areNodeLabelsOn ? 2 : 1}
linkOpacity={areNodeLabelsOn ? 0.5 : 0.4}
linkColor={linkColorDetermine}
linkDirectionalParticles={6}
nodeLabel={areNodeLabelsOn ? undefined : nodes => ${nodes.id || 'SomE ThinG'} :: ${nodes.description || 'Empty Description'}}
/>

);

from 3d-force-graph.

longlp-sosene avatar longlp-sosene commented on July 20, 2024

sprite.position.x = 0; sprite.position.y = 0; sprite.position.z = 8;
Yeah, but the problem is when you rotate, the label will be behind node :D

from 3d-force-graph.

longlp-sosene avatar longlp-sosene commented on July 20, 2024

Thank you Le Phi for replying. I got some un-referenced variables compiler errors:

import { CSS2DRenderer, CSS2DObject } from 'three/examples/jsm/renderers/CSS2DRenderer.js';

// Is your Graph variable this: const Graph = useRef(); // If not this then I need your Graph declaration / definition.

// I have this three library import, but you are referencing a THREE.Vector3() // what is your THREE definition? import { Group, Mesh, MeshBasicMaterial, SphereGeometry, Sprite, SpriteMaterial, Texture } from 'three';

// What is your highlight variable defined as ? let fontSize = controls['Font size'] + highlight;

const Graph = ForceGraph3D({ extraRenderers: [new CSS2DRenderer()] }) (container3DGraph) .backgroundColor('#1C1C1E') .enableNodeDrag(true) .enableNavigationControls(true) ....

import * as THREE from 'three';
just remove highlight

from 3d-force-graph.

dhilst avatar dhilst commented on July 20, 2024

By default, when I hover the mouse over a node I get the label displayed, is there any way to use the same mechanism to toggle the label visibility? I would like to toggle the node label visibility on click

Do I need SpriteText for that?

Great project BTW πŸŽ‰ !!

from 3d-force-graph.

longlp-sosene avatar longlp-sosene commented on July 20, 2024

By default, when I hover the mouse over a node I get the label displayed, is there any way to use the same mechanism to toggle the label visibility? I would like to toggle the node label visibility on click

Do I need SpriteText for that?

Great project BTW πŸŽ‰ !!

You can handle it by using SpriteText or CSS2DObject with default opacity of text color = 0,
and using highlight when click on node onNodeClick or onNodeHove (see example for more detail) to set opacity = 1

from 3d-force-graph.

Related Issues (20)

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    πŸ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. πŸ“ŠπŸ“ˆπŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❀️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.