
When working with animations, visualizations, or time-based data transformations, it’s often useful to map an increasing timestamp into an oscillating pattern — something that cycles smoothly up and down, back and forth, or in a “zigzag” manner. This can help create effects like pulsing, bouncing, or alternating motion without complex trigonometry.
In this article, we explore a simple and elegant way to transform a continuously increasing timestamp into a zigzag (triangle wave) pattern using plain JavaScript, with minimal arithmetic and no external libraries.
Suppose you have a timestamp t that increases monotonically — for example, it could be frame count, elapsed seconds, or any progressive integer/float value. You want to convert this into a value that oscillates around zero in a smooth, repeating zigzag:
...→ 1 → 0 → -1 → 0 → 1 → 0 → -1 → ...
The pattern repeats every 4 units of t, cycling between 1 and -1 in a piecewise linear fashion.
Here’s the one-liner that accomplishes this:
t = Math.abs(t % 4 - 2) - 1;
t % 4
This takes the timestamp modulo 4, wrapping t into the range [0, 4) repeatedly.(t % 4) - 2 maps to [-2, 2).Math.abs(...)
Taking the absolute value folds the range into a “V” shape: values go from 2 down to 0, then back to 2.1 and -1.t | t % 4 | (t % 4) - 2 | Math.abs(...) | Result t |
|---|---|---|---|---|
0 | 0 | -2 | 2 | 1 |
1 | 1 | -1 | 1 | 0 |
2 | 2 | 0 | 0 | -1 |
3 | 3 | 1 | 1 | 0 |
4 | 0 | -2 | 2 | 1 |
This gives the repeating zigzag pattern:
1 → 0 → -1 → 0 → 1 → 0 → -1 → ...
While sine or cosine functions provide smooth oscillations, they rely on more expensive floating-point calculations, and sometimes you want a linear, piecewise pattern instead of a smooth curve.
Advantages of this technique:
You can easily change the period and amplitude of the zigzag by introducing variables:
functionzigzag(t, period = 4, amplitude = 1) {
return amplitude * (Math.abs((t % period) - period / 2) - period / 4) / (period / 4);
}
period controls how many time units it takes to complete a full cycle.amplitude scales the peak value.For example:
zigzag(0); // 1
zigzag(1); // 0
zigzag(2); // -1
zigzag(3); // 0
zigzag(4); // 1 (cycle repeats)
If you know t is an integer, you can replace modulo with bitwise AND for speed:
t = Math.abs((t & 3) - 2) - 1;
Because t & 3 is equivalent to t % 4 for non-negative integers but generally faster.
Transforming an increasing timestamp into a zigzag or triangle wave is simple with the formula:
t = Math.abs(t % 4 - 2) - 1;
This elegant expression gives you a repeating piecewise linear oscillation between 1 and -1 with a period of 4 units, without the need for complex math or libraries.
By adjusting constants or wrapping this into a reusable function, you can easily customize period and amplitude for many creative and performance-sensitive applications.