Search code examples
javascriptmathtrigonometryafter-effects

Generating a smooth sine wave transition from one set of value to another with Javascript


What I'm trying to do is have a smooth transition from sine wave with a given set of values to another wave with a different value without introducing a kink into the sin wave. I'm at the fringes of my Maths knowledge so it anyone has any idea how to achieve this it would be greatly appreciated. I have looked at other questions and I have a gut feeling the answer is in a signal processing question.. phase vs time, instead of speed (or frequency) vs time. Just not sure how to adapt it to suit my code.

This link (bottom of the page) shows a working example of showing a waveform continously changing on the fly without any jumps in the wave when you change the value page link

Its all to generate the wing beats of a butterfly in after effects (which uses javascript) by changing the y axis angle on a graphic of a wing.

I used this formula: amplitude * Math.sin(time*speed)+bias

  • amplitude being the variation in angle I want the wing to move
  • speed is the speed of the wings beating
  • time is the timeline (a value in seconds) of the animation
  • bias being used to shift the angle (amplitude 45, bias 0, wing moves from -45 to 45 degrees. Change the bias to 45 and the wing moves from 0 to 90 degrees)

It all works fine until I need to change any of the key values amplitude, speed and bias. The animation has a jump in it or a flicker. I found some graph representations of what's happening, but not quite sure how to fix it in the code to create a smooth transition.

This image shows one of the kinks I'm getting

This image shows another kink in the wave

This image shows the smooth transition of what I'm trying to achieve

Many thanks for your time and any feedback you may have.


Solution

  • @Meeesta I was looking to create an effect similar to the mathisfun example you shared. I was successful by adjusting my usual formula/approach to generate the wave. So rather than:

    y = Math.sin(elapsedTime + frequency) * amplitude); // Don't do this for this scenario
    

    Instead I do this on each update step (pseudo code):

    // y value
    phase -= frequency * deltaTime;
    y = Math.sin(phase) * amplitude;
    
    // x value
    waveSpeed = frequency * wavelength * deltaTime;
    x -= waveSpeed; // do this for each point in your wave line to shift the wave left
    

    Here is a working example.

    I am not sure the math is 100% accurate in terms of the wave form generated but the effect is right and it's close enough for my purposes.