JSFiddle - React, Tailwind, and code Playground

by Paul West

HTML

<script src="https://threejs.org/build/three.min.js"></script>
<script src="https://threejs.org/examples/js/controls/OrbitControls.js"></script>

CSS

body {
  overflow: hidden;
  margin: 0;
}

JavaScript

var scene = new THREE.Scene();
var camera = new THREE.PerspectiveCamera(60, window.innerWidth / window.innerHeight, 1, 1000);
camera.position.set(0, 0, 10);
var renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);

var cylGeom = new THREE.CylinderBufferGeometry(1, 1, 10, 32, 50);

var uniforms = {
  mouse: {
    value: new THREE.Vector3()
  },
  radius: {
  	value: 3
  }
};

var cylMat = new THREE.PointsMaterial({
  size: 0.125,
  color: "aqua"
});
cylMat.onBeforeCompile = shader => {
	shader.uniforms.mouse = uniforms.mouse;
  shader.uniforms.radius = uniforms.radius;
  //console.log(shader.vertexShader);
  shader.vertexShader = `
  	uniform vec3 mouse;
    uniform float radius;
  ` + shader.vertexShader;
  shader.vertexShader = shader.vertexShader.replace(
  	`#include <begin_vertex>`,
    `#include <begin_vertex>
    	
      vec3 dir = transformed - mouse;
      
      float dist = length(dir);
			
      if (dist < radius){
        float ratio = 1. - dist / radius;

        vec3 shift = dir * 2. * (ratio * ratio);

        transformed += shift;
      }
    
    `
  );
}

var cyl = new THREE.Points(cylGeom, cylMat);
scene.add(cyl);

var plane = new THREE.Plane(new THREE.Vector3(0, 0, 1), 0);
var raycaster = new THREE.Raycaster();
var mouse = new THREE.Vector2();
window.addEventListener("mousemove", event =>{
	mouse.x = ( event.clientX / window.innerWidth ) * 2 - 1;
	mouse.y = - ( event.clientY / window.innerHeight ) * 2 + 1;
  
  raycaster.setFromCamera(mouse, camera);
  
  raycaster.ray.intersectPlane(plane, uniforms.mouse.value);
});

renderer.setAnimationLoop(() => {
  renderer.render(scene, camera)
});