How to Use MathUtils.pingpong in Three.js
In Three.js, creating smooth, back-and-forth animations often
requires oscillating values. This article explains how to utilize the
MathUtils.pingpong function to generate these oscillating
values over time, complete with practical code examples showing how to
apply this motion to 3D object properties like position, rotation, and
scale.
Understanding MathUtils.pingpong
The THREE.MathUtils.pingpong utility function is
designed to bounce a value back and forth between 0 and a
specified maximum limit. It behaves like a wave, constantly incrementing
up to the limit and then reversing direction back to zero.
The syntax for the function is:
THREE.MathUtils.pingpong(x, length);x: The input value, which is typically a continuously increasing number, such as elapsed time.length: The maximum value of the oscillation. The output will bounce back and forth between0and this number.
Implementing Pingpong in the Animation Loop
To create continuous oscillation over time, you should use
MathUtils.pingpong inside your active render/animation loop
alongside a THREE.Clock to track elapsed time.
Here is a basic implementation:
import * as THREE from 'three';
// Set up scene, camera, renderer, and mesh
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 geometry = new THREE.BoxGeometry();
const material = new THREE.MeshBasicMaterial({ color: 0x00ff00 });
const cube = new THREE.Mesh(geometry, material);
scene.add(cube);
camera.position.z = 5;
// Initialize the Clock to track elapsed time
const clock = new THREE.Clock();
function animate() {
requestAnimationFrame(animate);
const time = clock.getElapsedTime();
// Oscillate the Y position between 0 and 2
cube.position.y = THREE.MathUtils.pingpong(time, 2);
renderer.render(scene, camera);
}
animate();Controlling Speed and Range
By default, the oscillation speed is dictated directly by the elapsed
seconds, and the value only moves in a positive range starting from
0. You can easily customize both the speed and the range of
the oscillation.
Adjusting Speed
To speed up or slow down the animation, multiply the time variable before passing it into the function:
const speed = 2.0; // Double the speed
cube.position.y = THREE.MathUtils.pingpong(time * speed, 2);Changing the Range (Offsetting)
Because pingpong always returns a value between
0 and length, you must apply mathematical
offsets if you want the value to oscillate into negative space (e.g.,
between -1 and 1).
Subtract half of the maximum length from the final result to center the oscillation around zero:
const length = 2;
// Oscillates between 0 and 2, then subtracts 1 to oscillate between -1 and 1
cube.position.y = THREE.MathUtils.pingpong(time, length) - (length / 2);