« Back to Posts

Loop Time

If I want to animate something in a consistent loop I might just start a counter. I can increment until I hit the maximum of my range, and then start decrementing until I hit the minimum. It could look something like this:

var counter = 0,
    min = 0,
    max = 5,
    increment = false;
for (var i=0; i < 20; i++) {
    if (counter === max || counter === min) {
        increment = !increment;
    }
    counter = (increment)
        ? ++counter
        : --counter;
}

But I don't think the timing would be consistent with different ranges. This might be better if I use some constantly changing variable like time. I can get the time represented in milliseconds:

function epoch() { return (new Date).getTime(); }
var startTime = epoch();

And then I can get the amount of time that has passed since we started:

function delta() { return (epoch() - startTime) / 1000; }

Now, I know Math.sin(x) will give me a number between -1 and 1, and that is pretty useful if we can pass the time to it:

function deltaSin() { return Math.abs(Math.sin(delta())); }

With deltaSin() I'm now looping from 0 to 1 at a consistent rate, but this isn't especially useful to me yet. What if I want to loop from 0 to 255 to generate an RGB value? Or coordinates from one side of the screen to the other? I can map to a range like this:

function map(x, in_min, in_max, out_min, out_max) {
    return (x - in_min) * (out_max - out_min) / (in_max - in_min) + out_min;
}

And now if I want a looping RGB value I can get it like this:

map(deltaSin(), 0, 1, 0, 255);

Or I can get coordinates:

var x = map(deltaSin(), 0, 1, xMin, xMax),
    y = map(deltaSin(), 0, 1, yMin, yMax);

I can do more interesting things if I set a multiplier to speed it up and slow it down, and an offset to make sure values aren't always the same.

function deltaSin(offset = 0, multiplier = 0) {
    var d = (delta() * multiplier) - offset;
    return Math.abs(Math.sin(d));
}

And then I can do this, which looks kinda neat:

function colorPre() {
    var r = map(deltaSin(0, 0.5), 0, 1, 163, 255),
        g = map(deltaSin(2, 0.5), 0, 1, 163, 255),
        b = map(deltaSin(4, 0.5), 0, 1, 163, 255);
    $('pre').css('background', `linear-gradient(135deg, rgba(255,237,214,1) 0%, rgba(${r},${g},${b},0.5) 100%)`);
}
var colorPreInterval = setInterval(colorPre, 100);