Search code examples
iosanimationbeziercifilter

How to create a bezier/cubic simplified animation for offline render?


I have to animate alpha of an element that is being calculated offline. Lets talk about the simple alpha animation. Alpha is zero, alpha grows to 1, stays a while and goes back to zero.

Something like the graph below:

enter image description here

The animations will have different times. I need something that I can give the time (t) and obtain the value (v).

This animation is to be put inside a CIFilter based class and used to animate that filter and because the result of this filter will be calculated offline there is no CALayer to add it on, so using CAKeyframeAnimation or CABasicAnimation is out of question.

If I could use a CALayer, I would do this:

CABasicAnimation* fadeInOut = [CABasicAnimation animation];
fadeInOut.keyPath = @"filters.myFilter.inputRadius";
fadeInOut.fromValue = @(0);
fadeInOut.toValue = @(10);
fadeInOut.duration = 0.2f;
fadeInOut.timingFunction = [CAMediaTimingFunction functionWithName: kCAMediaTimingFunctionEaseInEaseOut];
fadeInOut.autoreverses = YES;

But the problem would be this line... there is no layer to add the animation. Like I said I am inside a CIFilter class!

[self.layer addAnimation:fadeInOut forKey:nil]; // NO WAY!

So, my question is: is there something that can give me the value of time for this kind of curve for the time Interval I define for the animation?


Solution

  • You're subclassing CIFilter and animating... I presume that means your filter class takes a time parameter, and varies its result based on that?

    If so, there are two options you could look into. Both rely on the fact that your desired timing curve looks like an "ease-in-ease-out" S-curve followed by that curve's reverse.

    1. If you're writing CI Kernel Language code to implement your filter's effect, you can interpolate based on your time parameter using the smoothstep function (that function is defined by GLSL, and CI Kernel Language is a superset of GLSL except where defined otherwise. Since you have a double S-curve, you'll need to do it twice:

      // pseudo CI Kernel source:
      effect = smoothstep(0, 0.5, time) - smoothstep(0.5, 1, time)
      
    2. If you're not writing a kernel, but instead implementing a filter in terms of other filters, you can define your own equivalent of the smoothstep function — that definition is well known and fairly simple, since it's in many graphics libraries. (Or you can learn about Hermite interpolation in general and go nuts with your own smoothing functions.) Then use your function to change the input to your internal filter based on your time parameter.