JSFiddle - React, Tailwind, and code Playground

HTML

<div class="grid js-grid">
	<div><figure class="js-plane" data-src="https://assets.codepen.io/58281/lama-3.jpg?width=1100&format=auto"></figure></div>
	<div><figure class="js-plane" data-src="https://assets.codepen.io/58281/lama-2.jpg?width=1100&format=auto"></figure></div>
	<div><figure class="js-plane" data-src="https://assets.codepen.io/58281/lama-1.jpg?width=1100&format=auto"></figure></div>
	<div><figure class="js-plane" data-src="https://assets.codepen.io/58281/lama-3.jpg?width=1100&format=auto"></figure></div>
	<div><figure class="js-plane" data-src="https://assets.codepen.io/58281/lama-2.jpg?width=1100&format=auto"></figure></div>
	<div><figure class="js-plane" data-src="https://assets.codepen.io/58281/lama-1.jpg?width=1100&format=auto"></figure></div>
	<div><figure class="js-plane" data-src="https://assets.codepen.io/58281/lama-3.jpg?width=1100&format=auto"></figure></div>
	<div><figure class="js-plane" data-src="https://assets.codepen.io/58281/lama-2.jpg?width=1100&format=auto"></figure></div>
	<div><figure class="js-plane" data-src="https://assets.codepen.io/58281/lama-1.jpg?width=1100&format=auto"></figure></div>
	<div><figure class="js-plane" data-src="https://assets.codepen.io/58281/lama-3.jpg?width=1100&format=auto"></figure></div>
	<div><figure class="js-plane" data-src="https://assets.codepen.io/58281/lama-2.jpg?width=1100&format=auto"></figure></div>
	<div><figure class="js-plane" data-src="https://assets.codepen.io/58281/lama-1.jpg?width=1100&format=auto"></figure></div>
	<div><figure class="js-plane" data-src="https://assets.codepen.io/58281/lama-1.jpg?width=1100&format=auto"></figure></div>
	<div><figure class="js-plane" data-src="https://assets.codepen.io/58281/lama-3.jpg?width=1100&format=auto"></figure></div>
	<div><figure class="js-plane" data-src="https://assets.codepen.io/58281/lama-2.jpg?width=1100&format=auto"></figure></div>
</div>

<div class="page js-page">

</div>
<script src="https://unpkg.com/gsap@3.12.2/dist/gsap.min.js"></script>

CSS

@import url('https://fonts.googleapis.com/css2?family=Roboto&display=swap');

html, body{
	height: 100%;
	height: 100%;
	overflow: hidden;
}

html{
	font-size: 1vw;
}

body{
	padding: 0;
	margin: 0;
	cursor: grab;
	user-select: none;
}

.grid{
	position: fixed;
	top: 0; left: 0;
	width: 150%;
	height: 150%;
	display: grid;
	grid-template-columns: repeat(5, 1fr);
	
	> div{
		position: relative;
	}
}

canvas{
	position: fixed;
	top: 0; left: 0;
	width: 100%; height: 100%;
	pointer-events: none;
}

figure{
	position: absolute;
	inset: 0.5rem;
	padding: 0;
	margin: 0;
}

JavaScript

import * as THREE from 'https://unpkg.com/three/build/three.module.js';

console.clear()

let ww = window.innerWidth
let wh = window.innerHeight

const isFirefox = navigator.userAgent.indexOf('Firefox') > -1
const isWindows = navigator.appVersion.indexOf("Win") != -1

const mouseMultiplier = .6
const firefoxMultiplier = 20

const multipliers = {
	mouse: isWindows ? mouseMultiplier * 2 : mouseMultiplier,
	firefox: isWindows ? firefoxMultiplier * 2 : firefoxMultiplier
}

/** CORE **/
class Core {

	constructor() {
		this.tx = 0
		this.ty = 0
		this.cx = 0
		this.cy = 0
		
		this.diff = 0
		
		this.wheel = { x: 0, y: 0 }
		this.on = { x: 0, y: 0 }
		this.max = { x: 0, y: 0 }
		
		this.isDragging = false
		
		this.tl = gsap.timeline({ paused: true })
		
		this.el = document.querySelector('.js-grid')
		
		/** GL specifics **/
		this.scene = new THREE.Scene()

		this.camera = new THREE.OrthographicCamera(
			ww / -2, ww / 2, wh / 2, wh / -2, 1, 1000
		)
		this.camera.lookAt(this.scene.position)
		this.camera.position.z = 1

		this.renderer = new THREE.WebGLRenderer({ antialias: true })
		this.renderer.setSize(ww, wh)
		this.renderer.setPixelRatio(
			gsap.utils.clamp(1, 1.5, window.devicePixelRatio)
		)

		document.body.appendChild(this.renderer.domElement)
		/** Gl specifics end **/
		
		this.addPlanes()
		this.addEvents()
		this.resize()
	}
	
	addEvents() {
		gsap.ticker.add(this.tick)

		window.addEventListener('mousemove', this.onMouseMove)
		window.addEventListener('mousedown', this.onMouseDown)
		window.addEventListener('mouseup', this.onMouseUp)
		window.addEventListener('wheel', this.onWheel)
	}
	
	addPlanes() {
		const planes = [...document.querySelectorAll('.js-plane')]
		
		this.planes = planes.map((el, i) => {
			const plane = new Plane()
			plane.init(el, i)
			
			this.scene.add(plane)
			
			return plane
		})
	}

	tick = () => {
		const xDiff = this.tx - this.cx
		const yDiff = this.ty - this.cy
		
		this.cx += xDiff * 0.085
		this.cx =...