I'm trying to make my first steps into Three.js, But I have a slight problem. I have a rotating icosahedron in the middle of my scene and when I click a button it should start rotating a bit faster, and the camera should get closer to it so it seems bigger. The problem is that I'm changing the distance / rotation speed in a linear fashion. What I want to achieve is to add some kind of acceleration curve to this animation.
Howewer... I'm lost. I've looked at tons of tutorials and examples but none of them explained to me how to achieve a cubic-bezier like effect.
I'm also trying to use GSAP to get it working but I've got no effects. If you're not able to help then maybe know any good articles where I can learn such stuff from? Or maybe a tutorial that covers such transitions?
So here's my code:
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera( 75, window.innerWidth / window.innerHeight, 0.1, 5000 );
let renderer = new THREE.WebGLRenderer({ alpha: true, antialias: true });
renderer.setSize( window.innerWidth, window.innerHeight );
document.body.appendChild( renderer.domElement );
window.addEventListener('resize',() => {
let width = window.innerWidth;
let height = window.innerHeight;
renderer.setSize( width, height );
camera.aspect = width / height;
camera.updateProjectionMatrix();
});
camera.position.z = 10;
var pointL1 = new THREE.PointLight( 0xffffff, 2, 30);
pointL1.position.x = -4;
pointL1.position.y = 7;
pointL1.position.z = 8;
scene.add( pointL1 );
var geometry1 = new THREE.IcosahedronGeometry(5, 1);
var material1 = new THREE.MeshBasicMaterial( { color: 0x222222, wireframe: true } );
var icosahedron = new THREE.Mesh( geometry1, material1 );
scene.add( icosahedron );
icosahedron.rotation.y -= 1;
let maxCameraDist = 10;
let minCameraDist = 8;
let cameraDist = 10;
let duringChange = false;
function render () {
if (duringChange == false) {
icosahedron.rotation.y += 0.001;
icosahedron.rotation.z += 0.001;
if (cameraDist < maxCameraDist) {
cameraDist += 0.05;
camera.position.z = cameraDist;
}
} else {
icosahedron.rotation.y += 0.003;
icosahedron.rotation.z += 0.003;
if (cameraDist > minCameraDist) {
cameraDist -= 0.05;
camera.position.z = cameraDist;
}
}
}
let loop = function() {
requestAnimationFrame(loop);
render();
renderer.render(scene, camera);
}
loop();
document.querySelector('button').addEventListener('click',() => {
if (duringChange == false) duringChange = true; else duringChange = false;
})
button {
padding: 20px;
position: absolute;
z-index: 2;
}
canvas {
position: absolute;
z-index: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
<body>
<button>Change it</button>
</body>
`
An example with a non-deprecated library - GSAP 3.
Eases are here: https://greensock.com/docs/v3/Eases
let scene = new THREE.Scene();
let camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 5000);
let renderer = new THREE.WebGLRenderer({
alpha: true,
antialias: true
});
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
window.addEventListener('resize', () => {
let width = window.innerWidth;
let height = window.innerHeight;
renderer.setSize(width, height);
camera.aspect = width / height;
camera.updateProjectionMatrix();
});
camera.position.z = 15;
var pointL1 = new THREE.PointLight(0xffffff, 2, 30);
pointL1.position.x = -4;
pointL1.position.y = 7;
pointL1.position.z = 8;
scene.add(pointL1);
var geometry1 = new THREE.IcosahedronGeometry(5, 1);
var material1 = new THREE.MeshBasicMaterial({
color: 0x222222,
wireframe: true
});
var icosahedron = new THREE.Mesh(geometry1, material1);
scene.add(icosahedron);
icosahedron.rotation.y -= 1;
let cameraDistFrom = 15;
let cameraDistTo = 8;
let rotSpeed = 0.1;
let clock = new THREE.Clock();
function render() {
let t = clock.getDelta();
icosahedron.rotation.y += rotSpeed * t;
icosahedron.rotation.z += rotSpeed * t;
}
let loop = function() {
requestAnimationFrame(loop);
render();
renderer.render(scene, camera);
}
loop();
document.querySelector('button').addEventListener('click', () => {
rotSpeed = 0.3;
gsap.fromTo(camera.position, {
z: cameraDistFrom
}, {
z: cameraDistTo,
duration: 1,
ease: "back.out(3)"
});
})
body {
overflow: hidden;
margin: 0;
}
button {
padding: 20px;
position: absolute;
z-index: 2;
}
canvas {
position: absolute;
z-index: 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/three.js/110/three.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/3.2.4/gsap.min.js"></script>
<body>
<button>Change it</button>
</body>