Update:
Well, it took me some time but I think I got it. Because you made your own 'custom' function, it was a bit harder to accomplish.
The Intuition
To explain everything I did, let's start with the absolute basis of linear formulas.
- Let's say we can visualise your custom function as a linear function
f(x)=x
- Let's say we can visualise the easing functions as a nonlinear function. For example let's say we consider the function
g(x)=sin(x)
as our easing function (this corresponds to the easing methodeaseInSine
)
Let's consider these functions in a two dimensional plot:
As you can see, I have now drawn two different functions. If we would visualise these functions as our functions in JavaScript, then they are two seperate functions we can call independently. For example:
function linear(x)
{
return x;
}
function sin(x)
{
return Math.sin(x);
}
Now we can use both these functions as a scrollTransition but that's not what we want.
You asked the specific question: How to add the nonlinear function to my custom linear function?
So let's consider some of the possibilities we have with our two functions:
- we can add them together
- we can substract them
- we can do nothing
- we can take the average
- etc...
Let's visualise the first point:
The grey lines indicate the original functions and the blue line are the functions added together.
For the second point we would get:
Where again, the grey lines indicate the original functions and the blue line are the functions added together. (well... in this case: 'subtracted from each other')
The Code
Let's consider everything we know:
- We know that your function gives back a certain linear-determined value
- We know that the easing functions give back a certain nonlinear-determined value
So just like with the graphs, we can add and substract these values to add the functions together.
To accomplish this with your function, I added two parameters to your function:
easingEffect
which should be the name of the nonlinear easing effect you want to add (or substract) from your custom functionplus
which can take on values-1
,0
and1
and which will determine how the nonlinear effect is handled:-1
the nonlinear function will be substracted from your custom linear function0
the nonlinear function will not be used1
the nonlinear function will be added to your custom linear function
An example of this would be:
$(".element").css({
"opacity": 1-scrollTransition(0, 1, 0, 400, scrollTop, "easeInSine", 1),
"left": scrollTransition(0, 200, 0, 300, scrollTop, "easeOutBounce", 1)
});
Then what I did within your function basically comes down to the following:
sum += plus*easingEffect(null, scrollTop, startValue, endValue, distance);
Where the easing effect is determined by the easing js you supplied yourself.
Unfortunately, I ended up doing a lot of manual work because for your custom function we need the easing functions to return values without having to call the jQuery.animate()
function. But you don't have to worry about that anymore: I did all the work already so you can now just sitback and play around with the settings to see what happens.
You can find the (fully implementable) solution here: the code at jsFiddle.
You can do some cool things like this.
Details for Implementation
Beware of the following things:
For opacity
, adding two values together is quite dangerous because the CSS property will give an error if you're trying to pass an argument that's bigger than 1
. Therefore I do the following:
"opacity": 1-scrollTransition(0, 1, 0, 400, scrollTop, "easeInSine", 1),
So I basically reverse the function (I let the function 'work' from 0 to 1 instead of from 1 to 0) and then I do 1-'the function'
to make sure the values are never above 1. Note that this should be coherent with substracting or adding the nonlinear function.
Also, if you scroll down in the javascript, you will see all the functions and the huge switch statement: you must add all of these to your final javascript file.
So what I suggest is that you just copy the whole javascript section to your own project.
Furthermore, the jsFiddle should be self-explanatory.
Good luck and I hope I answered your question!
UPDATE 2
demrks
did the following:
sum = easeOutBounce(null, sum, startValue, endValue, distance);
To gain more intuition about adding the parameter sum
to the easing functions, consider the following graph:
Where the blue line indicates the outcome of your function.
So what your are basically doing is called a linear transformation
of the easing function or linear mapping
the easing function. You can read more about this here.
But what it basically comes down to is that you are changing 'the form' of the easing function by the following properties:
- How fast the easing animation 'goes'
- When it starts/ terminates
So if that is what you want to accomplish, then its perfectly fine and you can use it outside of jsFiddle as well. To me it seems a bit messy, though, because you lose control over the exact animation of the whole (the joint function) since you added an extra level of complexity to the parameters. Or in other words: the programming becomes harder because you don't know exactly what the outcome will be.
I hope that answers your last point of interest as well :)
Happy programming!
UPDATE 3
demrks
asked why the easing functions have limitations on their parameters.
Let's consider such a easing
function:
function easeOutBounce(x, t, b, c, d) {
if ((t/=d) < (1/2.75)) {
return c*(7.5625*t*t) + b;
} else if (t < (2/2.75)) {
return c*(7.5625*(t-=(1.5/2.75))*t + .75) + b;
} else if (t < (2.5/2.75)) {
return c*(7.5625*(t-=(2.25/2.75))*t + .9375) + b;
} else {
return c*(7.5625*(t-=(2.625/2.75))*t + .984375) + b;
}
}
//x = null;
//t = currentTime;
//b = begin;
//c = end;
//d = distance;
Simply by looking at the function we come to the following conclusions:
- If
c=0
, then the function will return the valueb
- If
b<0
andc=0
, then the function will return the negative valueb
- If
- If
c<0
, then the function will return a negative value
Note that we have defined opacity as:
"opacity": 1-scrollTransition(0, 1, 0, 400, scrollTop, "easeInSine", 1)
Hence if the function scrollTransition(0, 1, 0, 400, scrollTop, "easeInSine", 1)
returns a negative value, we will have an error in the $(".element").css(...);
property and so nothing will happen.
So basically the easing functions work fine. Just if you apply them to the property opacity we sometimes have the constraint:
endValue > 0
Talking about the behaviour of functions, let's consider another one:
function easeInOutElastic(x, t, b, c, d) {
var s=1.70158;var p=0;var a=c;
if (t==0) return b; if ((t/=d/2)==2) return b+c; if (!p) p=d*(.3*1.5);
if (a < Math.abs(c)) { a=c; var s=p/4; }
else var s = p/(2*Math.PI) * Math.asin (c/a);
if (t < 1) return -.5*(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
return a*Math.pow(2,-10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )*.5 + c + b;
}
Note that for this one, the function is highly dependent on the variable d
(distance).
Hence, the formulas work fine.
It's just that you have to be careful for how you apply them and how they behave that might make things complicated.
What's wrong with jsFiddle
Regarding working in jsFiddle, be very careful of how you initialise your document.
For example I found that animating from -300
to 200
with easing works fine IF you put the document width
larger than the animation space (space that the animation needs to execute properly).
You can see a working code of animating from -300
to 200
here.
Note that I changed the document width:
body {
height: 2000px;
width: 800px;
}
That should answer your question. Good luck!
Update 4
To shorten the switch statement
, you can also use:
var call = eval(easingEffect);
sum += call(null, scrollTop, startValue, endValue, distance);
As you can see in THIS example. That might save you some manual work.