Статьи

Как использовать Three.js, облегченную 3D-библиотеку, с Neo4j

На прошлой неделе мы видели Sigma.js , и, как и было обещано, здесь представлена ​​визуализация графиков с Three.js и Neo4j . Three.js — это легкая 3D-библиотека, написанная г-ном Дубом и небольшой группой авторов.

То, что вы можете сделать с Three.js, поразительно, и моя небольшая демонстрация здесь не дает справедливости, но, тем не менее, я покажу вам, как это сделать.

Нам нужно передать узлы и отношения в Three.js, один из способов, которым мы можем легко это сделать, — с помощью камня Gon , так как мы используем sinatra, мы будем использовать специальный камень gon-sinatra .

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

На наш взгляд, мы добавим «include_gon», который связывает наши узлы и ребра с нашей HTML-страницей.

<!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>

Если вы просмотрите источник index.html, вы увидите наши узлы и ребра.

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}
           ...
           ]

Чтобы использовать Three.js, нам нужно создать камеру, сцену и выбрать рендер для использования.

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 );

Для создания наших узлов мы будем использовать сферы и использовать обычный материал. Мы возьмем узлы из gon и используем их свойства для позиционирования и установки ориентации наших сфер.

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 (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)
}

Мы будем анимировать нашу визуализацию, визуализируя сцену и управляя камерой с помощью мыши.

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 );
}

Я собираюсь пропустить создание графика, но весь код, как обычно, доступен на github , и вам наверняка захочется увидеть это вживую на Heroku .

Если вы хотите узнать больше о Three.js, ознакомьтесь с этим руководством и этими видео .