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 =...