<div id="options">
<p>From: <span id="randFrom"></span></p>
<p>Easing: <span id="randEasing"></span>
</div>
<a id="staakLogo" class="link" href="https://www.staak.co.uk/?ref=codepen&id=XowdeE" target="_blank" rel="noreferrer noopener">
<svg class="link" xmlns="http://www.w3.org/2000/svg" viewBox="17 348.4 630.7 145.5">
<path class="link" d="M255.4 450.9c-2.1 6.7-2.9 12.1-2.9 16.4 0 15.2 15 22.7 26 22.7v1.2h-59.9l.1-1.3c9.6 0 17.3-8.5 24-22.6l28.5-59.9.6 1.9c-7.1 15.4-12.3 27.9-15.4 37.8M381 490v1.2h-75V490c9.6 0 18.1-6.2 12.9-17l-39.3-82.7 19-42.5h2.1l61.5 131.4c3.8 8.1 8.6 10.8 18.8 10.8z"
/>
<path class="link" d="M386 450.2c-2.1 6.7-2.9 12.1-2.9 16.4 0 15.2 15 22.7 26 22.7v1.2h-59.9v-.8c9.6 0 17.5-8.9 24.1-23.1l28.5-59.9.6 1.9c-7.1 15.4-12.3 27.9-15.4 37.8M511.1 490v1.2h-75V490c9.6 0 18.1-6.2 12.9-17l-39.3-82.7 19.1-42.5h2.1l61.5 131.4c3.7 8.1 8.5 10.8 18.7 10.8z"
/>
<path class="link" d="M559.7 490v1.2h-66.3V490c12.5 0 15.6-5 15.6-10.6V362c0-5.6-3.1-10.8-15.6-10.8v-1.3h66.3v1.2c-12.3 0-15.4 5.2-15.4 10.8v117.5c0 5.6 3.2 10.6 15.4 10.6zm88.4 0v1.2h-68.2V490c6.4 0 11-3.1 11-7.3 0-4.4-1.2-6.7-2.9-9.1l-32.6-49.9c32.2-32.4 38.3-51.6 38.3-60.9 0-8.1-8.1-11.6-13.9-11.6v-1.3h61.1v1.2c-8.9 0-13.9 4.2-20.4 10.4L580.2 400l52.2 79.6c4 6.3 8 10.4 15.7 10.4zM19.1 442.6h-1.7v50.7h1.7l6.9-10.2c10.8 6.7 23.9 9.8 40.3 10.2v-1.2c-25.6-8.6-40.4-26-47.2-49.5zM48 368.2c0-11.4 8.7-17.5 18.3-19.1v-1.3C38.6 349.7 18.4 364 18.4 389c0 42.2 79.4 45.5 79.4 81.9 0 12.5-11.2 19.1-22.7 21.2v1.2c32.2-1.2 52.2-15.8 52.2-42.6.1-42.2-79.3-46.1-79.3-82.5zM204.9 479V349.9h-35.3V479c0 5.6-3.1 11-15.6 11v1.2h66.5V490c-12.5 0-15.6-5.4-15.6-11zM215.3 349.9v1.2c16 4 28.5 22.5 33.7 44.9h1.7v-46.1h-35.4zM159.2 349.9h-39.1l-7.5 8.9c-9.6-6.8-21.8-10.4-37.4-11v1.2c21.3 4.3 45.1 29.5 47.2 55.8l.2 4.1c6.2-34.7 20.2-53 36.6-57.8v-1.2z"
/></svg>
</a>
body, html {
margin: 0;
padding: 0;
display: flex;
font-family: arial;
}
#options {
width: 300px;
position: absolute;
top: 0px;
left: 20px;
color: #fff;
text-align: left;
}
h1 {
font-size: 26px;
}
p {
font-size: 18px;
line-height: 14px;
}
span {
border-bottom: 1px dotted #fff;
}
#staakLogo {
width: 4vw;
max-width: 100px;
min-width: 80px;
position: absolute;
bottom: 10px;
left: 10px;
z-index: 20;
padding: 10px;
}
#staakLogo svg {
width: 100%;
display: block;
}
#staakLogo svg path {
fill: #ffffff;
-webkit-transition: fill 0.25s ease-in-out;
transition: fill 0.25s ease-in-out;
}
class App {
constructor() {
this.randFrom = [
'first',
'last',
'center'
];
this.easing = [
'linear',
'easeInOutQuad',
'easeInOutCubic',
'easeInOutQuart',
'easeInOutQuint',
'easeInOutSine',
'easeInOutExpo',
'easeInOutCirc',
'easeInOutBack',
'cubicBezier(.5, .05, .1, .3)',
'spring(1, 80, 10, 0)',
'steps(10)'
];
this.randFromText = document.getElementById('randFrom');
this.randEasingText = document.getElementById('randEasing');
}
init() {
this.camera = new THREE.PerspectiveCamera( 25, window.innerWidth / window.innerHeight, 0.1, 1000 );
this.camera.position.x = -45;
this.camera.position.y = 30;
this.camera.position.z = -45;
// this.controls = new THREE.OrbitControls(this.camera);
this.camera.lookAt(new THREE.Vector3(5,-5,5));
this.scene = new THREE.Scene();
this.resizeListener = e => this.onResize(e);
window.addEventListener( 'resize', this.resizeListener, false );
this.createBoxes();
this.renderer = new THREE.WebGLRenderer({
antialias: true
});
this.renderer.setPixelRatio(window.devicePixelRatio);
this.renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( this.renderer.domElement );
this.beginAnimationLoop();
this.animate();
}
createBoxes() {
this.geometry = new THREE.BoxBufferGeometry(1, 10, 1);
let vertexShader = `
varying vec2 vUv;
void main() {
vUv = uv;
gl_Position = projectionMatrix * modelViewMatrix * vec4(position,1.0);
}
`;
let fragmentShader = `
#extension GL_OES_standard_derivatives : enable
varying vec2 vUv;
uniform float thickness;
float edgeFactor(vec2 p){
vec2 grid = abs(fract(p - 0.5) - 0.5) / fwidth(p) / thickness;
return min(grid.x, grid.y);
}
void main() {
float a = edgeFactor(vUv);
vec3 c = mix(vec3(1), vec3(0), a);
gl_FragColor = vec4(c, 1.0);
}
`;
let material = new THREE.ShaderMaterial({
uniforms: {
thickness: {
value: 1.5
}
},
vertexShader,
fragmentShader
});
let cube = new THREE.Mesh( this.geometry, material );
let offset = 1.25;
this.nRows = 25;
this.nCols = 25;
this.staggerArray = [];
for(var column = 0; column < this.nCols; column++) {
for(var row = 0; row < this.nRows; row++) {
let obj = cube.clone();
obj.position.x = (row * offset) - ((this.nRows*0.5) + (this.geometry.parameters.width*0.5));
obj.position.y = -(this.geometry.parameters.height*0.5);
obj.position.z = (column * offset) - ((this.nCols*0.5) + (this.geometry.parameters.width*0.5));
this.staggerArray.push(obj.position);
this.scene.add(obj);
}
}
}
beginAnimationLoop() {
// random from array
let randFrom = this.randFrom[Math.floor(Math.random()*this.randFrom.length)];
let easingString = this.easing[Math.floor(Math.random()*this.easing.length)];
this.randFromText.textContent = randFrom;
this.randEasingText.textContent = easingString;
anime({
targets: this.staggerArray,
y: [
{value: (this.geometry.parameters.height*0.25), duration: 500},
{value: -(this.geometry.parameters.height*0.25), duration: 2000},
],
delay: anime.stagger(200, {grid: [this.nRows, this.nCols], from: randFrom}),
easing: easingString,
complete: (anim) => this.beginAnimationLoop()
});
}
animate() {
requestAnimationFrame( () => this.animate() );
this.update();
this.render();
}
update() {
// update orbit controls
if(this.controls) {
this.controls.update();
}
}
render() {
this.renderer.render( this.scene, this.camera );
}
onResize() {
// scene & camera update
this.camera.aspect = window.innerWidth / window.innerHeight;
this.camera.updateProjectionMatrix();
this.renderer.setSize( window.innerWidth, window.innerHeight );
}
}
let app = new App();
app.init();
This Pen doesn't use any external CSS resources.