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