adding the code the above fiddle here for future:
import * as CONTROLS from 'https://alikim.com/_v1_jsm/controls.js'
import * as THREE from 'https://unpkg.com/three/build/three.module.js'
import * as MathUtils from 'https://unpkg.com/three/src/math/MathUtils.js'
const scene = new THREE.Scene();
const camera = new THREE.PerspectiveCamera(75, window.innerWidth / window.innerHeight, 0.1, 1000);
const renderer = new THREE.WebGLRenderer();
renderer.setSize(window.innerWidth, window.innerHeight);
document.body.appendChild(renderer.domElement);
const hlp = new THREE.AxesHelper(3);
const sphere = new THREE.Mesh(
new THREE.SphereGeometry(0.2, 16, 16),
new THREE.MeshBasicMaterial({color:0x800080}),
);
const sphere1 = sphere.clone();
const sphere2 = sphere.clone();
const sphere3 = sphere.clone();
scene.background = new THREE.Color(0x002200);
scene.add(hlp).add(sphere).add(sphere1).add(sphere2).add(sphere3);
camera.position.set(5, 3, 5);
camera.lookAt(0, 0, 0);
const duration = 3000;
const idur = 1 / duration;
let t0 = performance.now();
const tick = (ease, now) => {
const dif = now - t0;
// quadratic filter
const s = dif ? Math.min(1, dif * idur) : 0;
const f = dif ? Math.min(1, -ease * s * s + (1 + ease) * s) : 0;
return f;
};
const v1 = new THREE.Vector3(0, 0, 3);
const v2 = new THREE.Vector3(0, 1, 3);
const smoothstep = now => {
const dif = now - t0;
const t = dif * idur;
return new THREE.Vector3().lerpVectors(v1, v2, MathUtils.smoothstep(t, 0, 1));
};
const render = (f0, f1, f2, v) => {
sphere.position.set(0, 2 * f0, 0);
sphere1.position.set(0, 2 * f1, 1);
sphere2.position.set(0, 2 * f2, 2);
sphere3.position.set(v.x, 2 * v.y, v.z);
renderer.render(scene, camera);
};
const state = {
play: true
};
const maybeRender = () => {
if (!state.play) render()
};
const framerate = 100;
const fpsint = 1000 / framerate;
let elapsed, now, then;
let tid = 0;
const animate = newtime => {
if (!state.play) return;
requestAnimationFrame(animate);
if (!newtime) then = newtime = window.performance.now();
now = newtime;
elapsed = now - then;
if (!fpsint || elapsed > fpsint) {
then = now - (elapsed % fpsint);
const [fy0, fy1, fy2, fy3] = [
tick(0, now),
tick(-1, now),
tick(1, now),
smoothstep(now)
];
if(fy0 == 1 && fy1 == 1 && fy2 == 1 && fy3.equals(v2) && !tid) {
tid = setTimeout(()=>{t0 = now; tid = 0; }, 1000);
}
render(fy0, fy1, fy2, fy3);
}
};
CONTROLS.create({
cont: renderer.domElement,
cam: camera,
type: 'Orbital',
overlay: true,
lookAt: [0, 0, 0],
callback: maybeRender
});
animate();