Move camera back-and-forth between two points

Hello,

Looking to get my camera view to basically bob up and down in a cute way.
Edit: Specifically, a slower, smoother camera oscillation along the Y axis.
GIF of problem - rapid oscillation: Imgur: The magic of the Internet

Could have gone the “make the GLBs oscillate instead of camera” route…
But I’m trying to figure out a transform for them and felt it’d get complicated for me.
I’m open to making the GLBs move, instead. Just need to ensure their KeyFrames still work.

Thank you for your help!

//*   Animation Loop (Pasted this first because it's likely the culprit)
function animate() {
    requestAnimationFrame(animate);

    // How to smooth/slow the sin(x) behavior to something pleasant?
    // Probably should be using a loop instead of math.random, too...
    camera.position.y = Math.sin(Math.random()) * -0.05;

    render();
    if (modelBGReady) modelBGMixer.update(modelBGClock.getDelta());
    if (modelUIReady) modelUIMixer.update(modelUIClock.getDelta());
    if (modelWebAppsReady)
        modelWebAppsMixer.update(modelWebAppsClock.getDelta());
    stats.update();
}
function render() {
    renderer.render(scene, camera);
}
animate();


// GLB Model (Just including this for completeness)
let modelBGReady = false;
let modelBGMixer: THREE.AnimationMixer;
const modelBGClock = new THREE.Clock();

const modelBGLoad = new GLTFLoader();
modelBGLoad.load(modelBG, (gltf) => {
    modelBGMixer = new THREE.AnimationMixer(gltf.scene);

    let animation = modelBGMixer.clipAction(gltf.animations[0]);
    animation.setLoop(THREE.LoopOnce, 1);
    animation.clampWhenFinished = true;
    animation.play();

    gltf.scene.rotation.z += modelRotateX;
    gltf.scene.rotation.y += modelRotateY;
    gltf.scene.position.set(0, -0.5, 0.2);
    scene.add(gltf.scene);
});

I would use GSAP for this: Edit fiddle - JSFiddle - Code Playground

You have the choice of a lot of easing functions to configure the animation (like speed and bounce effect).

you could port drei/camerashake drei/CameraShake.tsx at 90f9ffae3c8b81203b95906ef9b8e56d3f7fa242 · pmndrs/drei · GitHub it allows you to create rather natural pitch, yaw and roll movement with noise functions and frequency.

try changing some parameters here: Staging and CameraShake - CodeSandbox

const config = {
  maxYaw: 0.1, // Max amount camera can yaw in either direction
  maxPitch: 0.1, // Max amount camera can pitch in either direction
  maxRoll: 0.1, // Max amount camera can roll in either direction
  yawFrequency: 0.1, // Frequency of the the yaw rotation
  pitchFrequency: 0.1, // Frequency of the pitch rotation
  rollFrequency: 0.1, // Frequency of the roll rotation
  intensity: 1, // initial intensity of the shake
  decay: false, // should the intensity decay over time
  decayRate: 0.65, // if decay = true this is the rate at which intensity will reduce at
  controls: undefined, // if using orbit controls, pass a ref here so we can update the rotation
}

otherwise you can get simple up/down movements by dropping clock.elapsedTime into Math.sin and then get some variation by adding/subtracting/multiplying it to cos atan etc. but without noise it won’t look as natural.

There’s a great tutorial by Simodev that shows how to do up/down motion for a first person camera.

WOW! So many replies!

I went with @Mugen87’s suggestion. Mainly because GSAP intrigues me.
I’m unsure if I’ll be able to wrap it into a bundle.js for production…
But I’ll think on that when I come to it. All I know is what Sean’s udemy class taught me.

This is a GIF of the current situation: Imgur: The magic of the Internet
It’s smooth in the browser. The GIF is just choppy.
Downloaded GSAP via “npm install gsap” in VSCode.
import { gsap } from ‘gsap’; is what I used to get the code below to work.

gsap.to(camera.position, {
    duration: 1.3,
    y: 1.25,
    ease: 'circ.out',
    repeat: -1,
    yoyo: true,
});

I wouldn’t say this is 100% a “case closed” since I’ve got to see if I can bundle gsap.
But, it definitely did what I was looking for. THANK YOU

1 Like