DZone
Thanks for visiting DZone today,
Edit Profile
  • Manage Email Subscriptions
  • How to Post to DZone
  • Article Submission Guidelines
Sign Out View Profile
  • Post an Article
  • Manage My Drafts
Over 2 million developers have joined DZone.
Log In / Join
Refcards Trend Reports Events Over 2 million developers have joined DZone. Join Today! Thanks for visiting DZone today,
Edit Profile Manage Email Subscriptions Moderation Admin Console How to Post to DZone Article Submission Guidelines
View Profile
Sign Out
Refcards
Trend Reports
Events
Zones
Culture and Methodologies Agile Career Development Methodologies Team Management
Data Engineering AI/ML Big Data Data Databases IoT
Software Design and Architecture Cloud Architecture Containers Integration Microservices Performance Security
Coding Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones AWS Cloud
by AWS Developer Relations
Culture and Methodologies
Agile Career Development Methodologies Team Management
Data Engineering
AI/ML Big Data Data Databases IoT
Software Design and Architecture
Cloud Architecture Containers Integration Microservices Performance Security
Coding
Frameworks Java JavaScript Languages Tools
Testing, Deployment, and Maintenance
Deployment DevOps and CI/CD Maintenance Monitoring and Observability Testing, Tools, and Frameworks
Partner Zones
AWS Cloud
by AWS Developer Relations
11 Monitoring and Observability Tools for 2023
Learn more
  1. DZone
  2. Data Engineering
  3. Databases
  4. How to Use Three.js, a Lightweight 3D Library, with Neo4j

How to Use Three.js, a Lightweight 3D Library, with Neo4j

Max De Marzi user avatar by
Max De Marzi
·
Apr. 16, 12 · Interview
Like (0)
Save
Tweet
Share
13.54K Views

Join the DZone community and get the full member experience.

Join For Free

last week we saw sigma.js , and as promised here is a graph visualization with three.js and neo4j . three.js is a lightweight 3d library, written by mr. doob and a small army of contributors.

the things you can do with three.js are amazing, and my little demo here doesn’t give it justice, but nonetheless i’ll show you how to build it.

we need to pass the nodes and relationships to three.js, one of the ways we can do that easily is with the gon gem , since we’re using sinatra, we’ll use the special gon-sinatra gem .

class app < sinatra::base
  register gon::sinatra
  
  def nodes
    neo = neography::rest.new
    cypher_query =  " start node = node:nodes_index(type='user')"
    cypher_query << " return id(node), node"
    neo.execute_query(cypher_query)["data"].collect{|n| {"id" => n[0]}.merge(n[1]["data"])}
  end  
  
  def edges
    neo = neography::rest.new
    cypher_query =  " start source = node:nodes_index(type='user')"
    cypher_query << " match source -[rel]-> target"
    cypher_query << " return id(rel), id(source), id(target)"
    neo.execute_query(cypher_query)["data"].collect{|n| {"id" => n[0], "source" => n[1], "target" => n[2]} }
  end
  
  get '/' do
    neo = neography::rest.new
    gon.nodes = nodes  
    gon.edges = edges
    erb :index
  end
end

in our view we will add”include_gon” which ties our nodes and edges to our html page.

<!doctype html>
<html lang="en">
	<head>
		<title>three.js and neo4j</title>
		<%= include_gon %>
		<meta charset="utf-8">
		<script type="text/javascript" src="three.js"></script>
		<link type="text/css" rel="stylesheet" href="neo_three.css"/>
	</head>
	<body>
		<script type="text/javascript" src="neo_three.js"></script>
	</body>
</html>

if you view the source of index.html, you’ll see our nodes and edges.

window.gon = {};
gon.nodes=[{"id":1,
            "rotation_x":5.061454830783556,
            "name":"zfbushqe",
            "position_y":256,
            "position_x":658,
            "position_z":577,
            "rotation_y":3.543018381548489},              
           {"id":2,
            "rotation_x":4.572762640225143,
            "name":"afntayhh",
            "position_y":-22,
            "position_x":510,
            "position_z":404,
            "rotation_y":2.2689280275926285}
            ...
gon.edges=[{"id":3,"source":1,"target":198},
           {"id":2,"source":1,"target":39},
           {"id":1,"source":1,"target":21}
           ...
           ]

to use three.js, we’ll need to create a camera, a scene and pick a renderer to use.

camera = new three.perspectivecamera( 75, window.innerwidth / window.innerheight, 1, 10000 );
camera.position.z = 100;

scene = new three.scene();

scene.add( camera );

renderer = new three.canvasrenderer();
renderer.setsize( window.innerwidth, window.innerheight );
container.appendchild( renderer.domelement );

to create our nodes, we’ll use spheres and use a normal material. we’ll grab the nodes from gon and use their properties to position and set the orientation of our spheres.

var geometry = new three.spheregeometry( 50, 8, 7, false );
var material = new three.meshnormalmaterial();
  
group = new three.object3d();

for (n in gon.nodes) {

  var mesh = new three.mesh( geometry, material );
  mesh.position.x = gon.nodes[n].position_x;
  mesh.position.y = gon.nodes[n].position_y;
  mesh.position.z = gon.nodes[n].position_z;
  mesh.rotation.x = gon.nodes[n].rotation_x;
  mesh.rotation.y = gon.nodes[n].rotation_y;
  mesh.matrixautoupdate = false;
  mesh.updatematrix();
  group.add( mesh );

}

scene.add( group );

for our edges, we’ll create simple lines of random colors between the source and target nodes.

for (n in gon.edges) {
  var line_segment = new three.geometry();
  line_segment.vertices.push( new three.vertex( group.children[gon.edges[n].source - 1].position ) );
  line_segment.vertices.push( new three.vertex( group.children[gon.edges[n].target - 1].position ) );
  var line = new three.line( line_segment, 
                            new three.linebasicmaterial( { color: math.random() * 0xffffff, 
                                                           opacity: 0.5 } ) );

  scene.add(line)
}

we’ll animate our visualization by rendering the scene and controlling the camera with the mouse.

document.addeventlistener( 'mousemove',  ondocumentmousemove,  false );

function ondocumentmousemove(event) {
  mousex = event.clientx - windowhalfx;
  mousey = event.clienty - windowhalfy;
}

function animate() {
  requestanimationframe( animate );
  render();
}

function render() {
  camera.position.x += ( mousex - camera.position.x ) * .05;
  camera.position.y += ( - mousey + 200 - camera.position.y ) * .05;
  camera.lookat( scene.position );
  renderer.render( scene, camera );
}

i’m going to skip the graph creation but all the code is available on github as usual, and you’ll definitively want to see this live on heroku .

if you want to learn more about three.js, check out these tutorial and these videos .

Neo4j Library

Opinions expressed by DZone contributors are their own.

Popular on DZone

  • How To Build an Effective CI/CD Pipeline
  • Using GPT-3 in Our Applications
  • Little's Law and Lots of Kubernetes
  • 10 Easy Steps To Start Using Git and GitHub

Comments

Partner Resources

X

ABOUT US

  • About DZone
  • Send feedback
  • Careers
  • Sitemap

ADVERTISE

  • Advertise with DZone

CONTRIBUTE ON DZONE

  • Article Submission Guidelines
  • Become a Contributor
  • Visit the Writers' Zone

LEGAL

  • Terms of Service
  • Privacy Policy

CONTACT US

  • 600 Park Offices Drive
  • Suite 300
  • Durham, NC 27709
  • support@dzone.com
  • +1 (919) 678-0300

Let's be friends: