JSFiddle - React, Tailwind, and code Playground

HTML

<script src="https://g.alicdn.com/code/lib/three.js/103/three.js"></script>

CSS

body {
				margin:0;
				font-family: 'inconsolata';
				font-size: 15px;
				line-height: 18px;
				overflow: hidden;
			}

			canvas { width: 100%; height: 100% }

JavaScript

var scene, camera, renderer, lights, mesh, bones;

			var state = {
				animateBones: false
			};

			function initScene() {
				scene = new THREE.Scene();
				camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 200 );
				camera.position.z = 30;
				camera.position.y = 30;
				camera.lookAt(0, 0, 0);

				renderer = new THREE.WebGLRenderer( { antialias: true } );
				renderer.setPixelRatio( window.devicePixelRatio );
				renderer.setSize( window.innerWidth, window.innerHeight );
				renderer.setClearColor( 0x000000, 1 );
				document.body.appendChild( renderer.domElement );

				lights = [];
				lights[ 0 ] = new THREE.PointLight( 0xffffff, 1, 0 );
				lights[ 1 ] = new THREE.PointLight( 0xffffff, 1, 0 );
				lights[ 2 ] = new THREE.PointLight( 0xffffff, 1, 0 );

				lights[ 0 ].position.set( 0, 200, 0 );
				lights[ 1 ].position.set( 100, 200, 100 );
				lights[ 2 ].position.set( - 100, - 200, - 100 );

				scene.add( lights[ 0 ] );
				scene.add( lights[ 1 ] );
				scene.add( lights[ 2 ] );

				initBones();

			}

			function createGeometry( sizing ) {

				var geometry = new THREE.CylinderBufferGeometry(
					5, // radiusTop
					5, // radiusBottom
					sizing.height, // height
					8, // radiusSegments
					sizing.segmentCount * 3, // heightSegments
					true // openEnded
				);

				var position = geometry.attributes.position;

				var vertex = new THREE.Vector3();

				var skinIndices = [];
				var skinWeights = [];

				for ( var i = 0; i < position.count; i ++ ) {

					vertex.fromBufferAttribute( position, i );

					var y = ( vertex.y + sizing.halfHeight );

					var skinIndex = Math.floor( y / sizing.segmentHeight );
					var skinWeight = ( y % sizing.segmentHeight ) / sizing.segmentHeight;

					skinIndices.push( skinIndex, skinIndex + 1, 0, 0 );
					skinWeights.push( 1 - skinWeight, skinWeight, 0, 0 );

				}

				geometry.addAttribute( 'skinIndex', new THREE.Uint16BufferAttribute( skinIndices, 4 )...