Comments (16)
Hi @vasturiano .
- Yes- the example works fine without the nodeThreeObject.
- generatesprite always returns a Sprite object created using a canvas and context path. Is this appropriate?
I'm working on a codesandbox.
from react-force-graph.
The ctx
is the canvas context onto which you should run the drawing commands (like fillRect
, beginPath
, etc). You can not pre-draw on a separate canvas and then apply it to the chart canvas.
The { id, x, y}
is just a way to unpack the node's data. You can simply replace that with:
.nodeCanvasObject((nodeData, ctx) => { ... }
The nodeData
is useful to let you define how a particular node should look like. For example, you may want node id = 1
to be drawn red, and id = 2
to be drawn green. You can do that by writing your drawing logic based on the nodeData
attributes.
from react-force-graph.
@wadehenning you should create a new canvas context as part of the operation of generating a THREE object. Remember that this canvas is not attached to the DOM, it serves only the purpose of the sprite construction, so you don't need to get it from or link it with the 3d graph itself.
from react-force-graph.
@wadehenning thanks for reaching out. You can set any custom geometries for the nodes, using the nodeThreeObject
prop.
Here's an example with custom geometries:
https://vasturiano.github.io/react-force-graph/example/custom-node-shape/index-three.html
https://github.com/vasturiano/react-force-graph/blob/master/example/custom-node-shape/index-three.html
from react-force-graph.
Thank you for focusing me on the nodeThreeObject. I think I am close to being able to plot a 2D curve (ignoring the Sprite part for now), but I am getting an error: TypeError: shape.extractPoints is not a function. Any thoughts?
My component code:
<ForceGraph3D
graphData={data}
nodeThreeObject={ ({id}) => new THREE.Mesh(
[
new THREE.ShapeBufferGeometry( {shape} )
][id%1],
new THREE.MeshPhongMaterial(
{ color: 0xf08000} )
)}
/>;
My shape:
// California
var californiaPts = [];
californiaPts.push( new THREE.Vector2( 610, 320 ) );
californiaPts.push( new THREE.Vector2( 450, 300 ) );
..................................
californiaPts.push( new THREE.Vector2( 610, 320 ) );
for( var i = 0; i < californiaPts.length; i ++ ) californiaPts[ i ].multiplyScalar( 0.25 );
var shape = new THREE.Shape( californiaPts );
from react-force-graph.
I think I'm doing something wrong with sending the shape to the component
from react-force-graph.
I have been working to get a simple custom shape plotted and I am getting the error: TypeError: Cannot read property 'extractPoints' of undefined.
Does my simple code look correct?
import React, { Component } from 'react';
import { ForceGraph2D, ForceGraph3D, ForceGraphVR } from 'react-force-graph';
import * as THREE from 'three';
export default class FocusGraph extends React.Component {
render() {
const {data, shape} = this.props;
console.log(shape)
return <ForceGraph3D
graphData={data}
nodeThreeObject={ ( {shape} ) => new THREE.Mesh(
[
new THREE.ShapeBufferGeometry( shape )
],
new THREE.MeshPhongMaterial(
{ color: 0xf08000,
side: THREE.DoubleSide} )
)}
/>;
}
}
My shape looks like this:
// California
var californiaPts = [];
californiaPts.push( new THREE.Vector2( 610, 320 ) );
californiaPts.push( new THREE.Vector2( 450, 300 ) );
...
californiaPts.push( new THREE.Vector2( 610, 320 ) );
for( var i = 0; i < californiaPts.length; i ++ ) californiaPts[ i ].multiplyScalar( 0.25 );
var shape = new THREE.Shape( californiaPts );
Thanks
from react-force-graph.
I'm sure I'll figure it out.
from react-force-graph.
I have been able to get all of your examples working, and I have been able to add custom shapes. But I am still having trouble with custom sprites of shapes. My sprite code seems to generate sprites, but I get an error message:
Uncaught TypeError: Cannot read property 'x' of undefined
at WebGLSpriteRenderer.render (aframe-master.js:12357)
at WebGLRenderer.render (aframe-master.js:27568)
at Function.tick (three-render-objects.module.js:100)
at Function.r.(:3000/anonymous function) [as tick] (http://localhost:3000/static/js/bundle.js:161238:1813)
at animate (3d-force-graph.module.js:391)
I hope that my code is close enough for your review.
First I have a simple React Component, followed by short code to make my sprite.
export default class SpriteCurves extends React.Component {
render() {
const {data, shape, geometry} = this.props;
return <ForceGraph3D
graphData={data}
nodeAutoColorBy="group"
nodeThreeObject={() => {
const sprite = generatesprite(shape);
return sprite;
}}
/>;
}
}
SPRITE CODE:
function generateTexture(shape) {
var canvas = document.createElement( 'canvas' );
canvas.width = 20;
canvas.height = 20;
var context = canvas.getContext( '2d' );
var canvasShape = shape;
return canvas;
};
export function generatesprite(shape){
var texture = new THREE.Texture( generateTexture(shape) );
texture.needsUpdate = true; // important!
var material = new THREE.SpriteMaterial( { map: texture, color: 0xffffff } );
material.sizeAttenuation = false;
var sprite = new THREE.Sprite( material );
console.log(sprite);
return sprite;
};
from react-force-graph.
Hi @wadehenning could you make an example online, on CodePen or similar so that it's easier to debug?
For now, I'd check whether:
- Does the example work fine if you don't use the
nodeThreeObject
prop? - Does
generatesprite
always return a non-null Three Object3D?
from react-force-graph.
Hi @vasturiano.
Your incisive questions helped me figure out the error I was getting and I think I am getting close. I am now focusing on simply getting my irregular polygons to plot as contexts in 2D. The links plot perfectly and I get no errors, but I also get no nodes at all. Any thoughts on this code? CTX is an array of contexts generated from my polygons. I have tried enclosing {CTX} in curly braces in the nodeCanvasObject with no change. Maybe I am just missing something regarding how to pass data into the component.
render() {
const {Shapes, data, CTX} = this.props;
console.log(CTX);
return <ForceGraph2D
graphData={data}
nodeLabel="id"
nodeCanvasObject={ CTX => {
() => { CTX.fill(); }
} }
/>;
}
}
from react-force-graph.
@wadehenning the signature of nodeCanvasObject
is
.nodeCanvasObject((<nodeData>, <canvas context>, <current global scale>) => { /* ... do something with the context for representing this node */ })
In your code above, you're not unpacking the function signature correctly, it should be (node, ctx) => {...}
.
Also you should do some drawing operations on the context, otherwise ctx.fill()
has nothing to fill.
Here's an example of using the nodeCanvasObject
that may be of help:
https://github.com/vasturiano/force-graph/blob/master/example/custom-node-shape/index.html
from react-force-graph.
@vasturiano in the line below, I don't understand where the values for the input parameters come from. What is the value of ctx and where is it coming from? Where are id, x,, y coming from when you don't call gData
until later? So in my code, I pre-draw the ctx polygons, save it in state and send it through props as array CTX.
.nodeCanvasObject(({ id, x, y }, ctx) => {
If I simply add my nodes
data to the function as an input parameter it does not help, so I clearly need something different.
Thank you!
from react-force-graph.
Hi @vasturiano
I would like to generate sprites from irregular polygons in a ForceGraph3D
component. The Sprite
requires a ctx
, ctx
only comes from a nodeCanvasObject
, but ForceGraph3D
requires a nodeThreeObject
. Do I need to define a canvas inside the component myself? Also, what do you think about how I try and create a Sprite here in my nodeThreeObject
? For me, this 3d-force-sprite component is the whole purpose; everything else is just trying to learn the API. Thank you.
export default class SpriteGraph extends React.Component {
componentDidMount(){
this.fg.d3Force('link').distance(links => links.area_dist)
.iterations(1);
}
generateTexture = (ctx, points, color) => {
ctx.fillStyle = color;
ctx.beginPath();
ctx.moveTo(points[0][0],points[0][1]);
for(let i=1; i<points.length;i++){
ctx.lineTo(points[i][0], points[i][1]);
}
ctx.fill();
return ctx;
}
render() {
const data = this.props.data;
const getColor = n => '#' + ((n * 1234567) % Math.pow(2, 24)).toString(16).padStart(6, '0');
return <ForceGraph3D
ref={el => { this.fg = el; }}
d3Force = { ('link', "distance")}
cooldownTime={90000}
graphData={data}
nodeLabel="id"
nodeThreeObject={({ id, points }, ctx) => new THREE.Sprite(
new THREE.SpriteMaterial(
new THREE.Texture(this.generateTexture(ctx, points, getColor(id)))
),
)}
/>;
}
}
from react-force-graph.
Hi @vasturiano
I am generating random data and trying to plot a sprite with a circle at each node. I do get tiny squares at each node; which to me indicates that a Sprite is being created, but there is a fail somewhere.
Here is a link to a code sandbox where the preview does not work. I think this is related to the force-graph package (it did preview intermittently when I first copied in the example Custom Node Geometries code) , and maybe you have some experience getting these things to render better in these environments.
from react-force-graph.
@vasturiano , I'm sorry that you've had to walk me through this sprite example-- this is the first time I have ever worked with three.js or canvas. What I have learned here has helped me in other components that require canvas, and I appreciate your time.
I don't know if you have had a chance to look at the code sandbox I put up- even though the preview does not work, at least the code is all on one page and it is a trivial example. Here is what my output looks like. It is making some sort of tiny sprite node, but does not include my circles.
from react-force-graph.
Related Issues (20)
- Expanded nodes by default when rendering HOT 4
- Attempted import error: 'AmbientLight' is not exported from 'three'. HOT 1
- "Highlights" example not working for me HOT 4
- Unable to Display Node Text in Stage Environment? HOT 1
- Can't access node position in nodeThreeObject HOT 7
- DOMException on CustomElementRegistry when using multiple modules HOT 2
- enable zooming, panning and rotating separately for 3d graph HOT 1
- how to prevent endless re-rendering? HOT 1
- How to draw curved lines between nodes HOT 2
- Any ideas how to implement curved connections as on screenshoot HOT 2
- appending nodes gives: Cannot create property 'vx' on string
- Performance issue when utilizing Parcel to build project.
- How to have coordinates of real positions of nodes according to the window when zoom in on hover HOT 2
- how to stop force directed graph from moving the nodes?
- how to get a graph with less spacing? HOT 3
- How can i add minimap for graph? HOT 1
- Uncaught TypeError: object null is not iterable HOT 1
- when add style zoom to root dom,node cannot trigger click and hover events
- The 3d graph suddenly hops or flickers at regular intervals HOT 1
- Is there an example of displaying a label on a link in ForceGraph2D? HOT 1
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 react-force-graph.