JSFiddle - React, Tailwind, and code Playground
HTML
<div id='render-container'>
<div id='select-target'></div>
<div id='render-target'></div>
</div>
<script src='https://s3.amazonaws.com/duhaime/blog/visualizations/line-segments-network/three.min.js'></script>
<script src='https://s3.amazonaws.com/duhaime/blog/visualizations/line-segments-network/trackball-controls.min.js'></script>
<script src='https://s3.amazonaws.com/duhaime/blog/visualizations/line-segments-network/tweenlite.min.js'></script>
<script type='x-shader/x-vertex' id='vertex-shader'>
precision highp float;
uniform mat4 modelViewMatrix;
uniform mat4 projectionMatrix;
uniform float transitionPercent;
uniform vec3 cameraPosition;
uniform float pointScale;
attribute vec3 position;
attribute vec3 translation;
attribute vec3 target;
attribute vec3 color;
varying vec3 vColor;
float scalePointZ(in vec4 pos, in vec3 cameraPosition) {
float zDelta = pow(pos[2] - cameraPosition[2], 2.0);
float delta = pow(zDelta, 0.5);
float scaled = pointScale / delta;
return scaled;
}
void main() {
vec3 t1 = position + translation;
vec3 t2 = position + target;
vec3 pos = mix(t1, t2, clamp(transitionPercent, 0.0, 1.0));
vec4 mvPos = modelViewMatrix * vec4(pos, 1.0);
gl_Position = projectionMatrix * mvPos;
gl_PointSize = 6.0;
vColor = color;
}
</script>
<script type='x-shader/x-fragment' id='fragment-shader'>
precision highp float;
varying vec3 vColor;
void main() {
// make points circular
//vec2 coord = gl_PointCoord - vec2(0.5);
//if (length(coord) > 0.5) discard;
// set point color
gl_FragColor = vec4(0.0, 0.0, 0.0, 1.0);
}
</script>
CSS
html,
body {
width: 100%;
height: 100%;
background: linear-gradient(#efefef, #efefef);
}
body {
margin: 0;
overflow: hidden;
}
div#select-target {
padding: 20px 0;
}
select {
-webkit-appearance: none;
-moz-appearance: none;
appearance: none;
font-family: 'Mallory';
text-indent: 0.01px;
text-overflow: '';
border: none;
padding: 7px 40px 7px 10px;
background-image: url(down-caret.png);
background-position: 90% 50%;
background-size: 15px;
background-repeat: no-repeat;
font-size: 1em;
text-transform: uppercase;
border: 1px solid #c7c7c7;
font-family: arial, sans-serif;
}
#render-container {
text-align: center;
max-height: 100%;
max-width: 100%;
padding-bottom: 20px;
}
#render-target {
margin: 0 auto;
width: 700px;
height: 700px;
}
JavaScript
/**
* constructor for the gl manager
**/
function World() {
this.renderTarget = document.querySelector('#render-target');
this.scene = this.getScene();
this.camera = this.getCamera();
this.renderer = this.getRenderer();
this.controls = this.getControls();
this.masterCounts = null; // {id: nMasters}
this.edges = null; // 2d array where [[master, app, app]]
this.positions = null; // {id: [x,y]}
this.z = 0; // flat z dim
this.loadData();
this.render();
}
World.prototype.getScene = function() {
return new THREE.Scene();
}
World.prototype.getContainerSize = function() {
var elem = this.renderTarget;
return {
w: elem.clientWidth,
h: elem.clientHeight,
}
}
World.prototype.getCamera = function() {
var size = this.getContainerSize();
var camera = new THREE.PerspectiveCamera(75, size.w/size.h, 0.01, 10);
camera.position.set(0.5, 0.5, -0.67);
return camera;
}
World.prototype.getRenderer = function() {
var renderer = new THREE.WebGLRenderer({antialias: true, alpha: true});
var size = this.getContainerSize();
renderer.setPixelRatio(window.devicePixelRatio);
renderer.setSize(size.w, size.h);
document.querySelector('#render-target').appendChild(renderer.domElement);
return renderer;
}
World.prototype.getControls = function() {
var controls = new THREE.TrackballControls(this.camera, this.renderer.domElement);
controls.zoomSpeed = 0.4;
controls.panSpeed = 0.4;
controls.target.set(0.5, 0.5, 1);
return controls;
}
World.prototype.render = function() {
requestAnimationFrame(this.render.bind(this));
this.renderer.render(this.scene, this.camera);
this.controls.update();
}
World.prototype.getPointScale = function() {
return window.devicePixelRatio * window.innerHeight * 0.00001;
}
World.prototype.loadData = function() {
get('https://s3.amazonaws.com/duhaime/blog/visualizations/line-segments-network/node-positions-twopi.json', function(data) {
this.positions = center(JSON.parse(data));
...