Comments (8)
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.
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.
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.
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.
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.
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.
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.
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)
- ζη»εΈδΈηζζθηΉι½ζ²‘ζιΎζ₯οΌηΉε»θηΉδΉεοΌθηΉδΌεε€ζ©ζ£
- LOD for abnormally large graphs
- onNodeClick work error
- Default Settings for "charge" force not clear in documentation please help!!
- Labels for 'regions' / groups.
- text-nodes example stopped working HOT 2
- When nodeThreeObject is used, three-spritetext gives an error
- Arrow bad positionning when linkCurvature(0)
- The text-links example is broken by the latest three.js release r161 HOT 1
- Progressive WebXR HOT 2
- How to show a - 1M nodes HOT 3
- Best way to add dynamic external object
- How to add custom lighting in nodes
- how to zoomin or zoomout canvas with mouse click
- linkThreeObject seem to be created new obj every tick
- any ideas on how to generate a planar graph?
- change background color HOT 1
- Contribution request idea proposal - nodes traversal visualization
- non tree graph
Recommend Projects
-
React
A declarative, efficient, and flexible JavaScript library for building user interfaces.
-
Vue.js
π Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
-
Typescript
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
-
TensorFlow
An Open Source Machine Learning Framework for Everyone
-
Django
The Web framework for perfectionists with deadlines.
-
Laravel
A PHP framework for web artisans
-
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.
-
Visualization
Some thing interesting about visualization, use data art
-
Game
Some thing interesting about game, make everyone happy.
Recommend Org
-
Facebook
We are working to build community through open source technology. NB: members must have two-factor auth.
-
Microsoft
Open source projects and samples from Microsoft.
-
Google
Google β€οΈ Open Source for everyone.
-
Alibaba
Alibaba Open Source for everyone
-
D3
Data-Driven Documents codes.
-
Tencent
China tencent open source team.
from 3d-force-graph.