アニメーションのコンテキストで機能を緩和することの意味。dojo、jquery、silverlight、flexなどのUIシステムにはイージング機能の概念があるようです。イージング機能の良い説明が見つかりませんでしたか?誰かがイージング機能の概念を説明したり、それらの良い説明を指摘したりできますか?私はフレームワークの特定の詳細ではなく、概念に興味がありますか?
イージングは場所に厳密に使用されていますか、それとも一般的であり、オブジェクトの任意のプロパティに適用できますか?
アニメーションのコンテキストで機能を緩和することの意味。dojo、jquery、silverlight、flexなどのUIシステムにはイージング機能の概念があるようです。イージング機能の良い説明が見つかりませんでしたか?誰かがイージング機能の概念を説明したり、それらの良い説明を指摘したりできますか?私はフレームワークの特定の詳細ではなく、概念に興味がありますか?
イージングは場所に厳密に使用されていますか、それとも一般的であり、オブジェクトの任意のプロパティに適用できますか?
An easing function is usually a function that describes the value of a property given a percentage of completeness. Different frameworks use slightly different variations, but the concept is easy to grasp once you get the idea, but it's probably best to look a few examples.
First lets look at the interface that all our easing functions will abide by.
Our easing functions will take several arguments:
0.0
to 1.0
).And will return a number which represents the value the property should be set to.
Note: this is the same signature that jQuery uses for its easing functions, which I'll be borrowing for examples.
The easiest to understand is a linear ease:
var linear = function(percent,elapsed,start,end,total) {
return start+(end-start)*percent;
}
And now to put this to use:
Lets say we had an animation that was going to go for 1000 milliseconds and was supposed to start at 0 and end at 50. Passing those values into our easing function should tell us what the actual value should be:
linear(0, 0, 0,50, 1000) // 0
linear(0.25, 250, 0, 50, 1000) // 12.5
linear(0.5, 500, 0, 50, 1000) // 25
linear(0.75, 750, 0, 50, 1000) // 37.5
linear(1.0, 1000, 0, 50, 1000) // 50
This is a pretty straight forward (no pun intended) tween. It is a simple linear interpolation. If you were to graph value vs time, it would be a straight line:
Lets take a look at a bit more complicated easing function, a quadratic ease in:
var easeInQuad = function (x, t, b, c, d) {
return c*(t/=d)*t + b;
}
And lets look at the same results, using the same inputs as before:
easeInQuad(0, 0, 0, 50, 1000) // 0
easeInQuad(0.25, 250, 0, 50, 1000) // 3.125
easeInQuad(0.5, 500, 0, 50, 1000) // 12.5
easeInQuad(0.75, 750, 0, 50, 1000) // 28.125
easeInQuad(1, 1000, 0, 50, 1000) // 50
Notice the values are very different than our linear ease. It starts out very slow, then accelerates to its ending point. At 50% completion of the animation it has only made it to a value of 12.5, which is one quarter of the actual distance between the start
and end
values we have specified.
If we were to graph this function it would look something like this:
Now lets take a look at a basic ease-out:
var easeOutQuad = function (x, t, b, c, d) {
return -c *(t/=d)*(t-2) + b;
};
This essentially does the "opposite" acceleration curve of an ease in. It starts out fast and then decelerates to its ending value:
And then there are functions that ease both in and out:
var easeInOutQuad = function (x, t, b, c, d) {
if ((t/=d/2) < 1) return c/2*t*t + b;
return -c/2 * ((--t)*(t-2) - 1) + b;
};
This function will start out slow and end slow, reaching its maximum velocity in the middle.
There are a bunch of easing/interpolations that you can use: Linear, Quadradic, Cubic, Quart, Quint, Sine. And there are specialty easing functions like Bounce and elastic, which have their own.
For example, an elastic ease in:
var easeInElastic = function (x, t, b, c, d) {
var s=1.70158;var p=0;var a=c;
if (t==0) return b; if ((t/=d)==1) return b+c; if (!p) p=d*.3;
if (a < Math.abs(c)) { a=c; var s=p/4; }
else var s = p/(2*Math.PI) * Math.asin (c/a);
return -(a*Math.pow(2,10*(t-=1)) * Math.sin( (t*d-s)*(2*Math.PI)/p )) + b;
},
Perhaps somebody else can explain the actual math part behind the interpolation, because honestly I'm not a math wiz. But that's the basic principle of the easing functions themselves.
When you start a tween/animation, the animation engine remembers the start and end values you want. Then each time it updates, its figures out of how much time has passed. It call the supplied easing function with the values to figure out the value the property should be set to. As long as all of the easing functions implement the same signature, they can be swapped out with ease, and the core animation engine doesn't have to know difference. (Which makes for an excellent separation of concerns).
You'll notice that I've avoided talking about x
and y
positions explicitly, because easing doesn't have anything specifically to do with position per se. An easing function just defines a transition between a start and end values. Those could be x
coordinates, or a color, or the transparency of an object.
And in fact, in theory, you could apply different easing function to interpolate for different properties. Hopefully this helps shed some light on the basic idea.
And here is a really cool example (that uses a slightly different signature, but is the same principle) to play with to get the idea of how easing relates to position.
Edit
Here is a little jsFiddle I threw together to demonstrate some of the basic usages in javascript. Notice that the top
property is tweened using bounce, and the left
property is tweened using a quad. Use the slider to simulate the render loop.
Since all the functions in the easing
object have the same signature, you can swap any of them out for each other. Right now most of these things are all hard-coded (things like start and end values, the tween functions that are used and the length of the animation), but in a real-world example of a animation helper, you would want to pass in the following properties:
undefined
then use its current value)The animation engine would keep track of these settings for the duration of the animation and during every update cycle, it would use the tweening argument to calculate the properties new value.
イージング関数は、アニメーションの速度を制御して目的の効果 (バウンス、ズームイン、スローなど) を与えるアルゴリズムです。
もう少し詳しく知りたい場合は、MSDNのコメントを参照してください。
受け入れられた回答がありますが、この古い質問への回答を投稿したいと思います。32bitkidさんが必要な説明をしてくれました。私が追加するのは、基本的な実用的な実装です。これは、見つけることができなかったからです (これについても質問を投稿しました)。
たとえば、この単純な線形アニメーションを見てみましょう。コードは一目瞭然なので、説明が必要だとは思いません。時間の経過とともに変化しない一定の増分値を計算し、反復ごとにボックスの位置を増やします。位置変数を直接変更してから、ボックスに適用しています。
var box = document.getElementById("box");
var fps = 60;
var duration = 2; // seconds
var iterations = fps * duration; // 120 frames
var startPosition = 0; // left end of the screen
var endPosition = window.innerWidth - box.clientWidth; // right end of the screen
var distance = endPosition - startPosition; // total distance
var posIncrement = distance / iterations; // change per frame
var position = startPosition; // current position
function move() {
position += posIncrement; // increase position
if (position >= endPosition) { // check if reached endPosition
clearInterval(handler); // if so, stop interval
box.style.left = endPosition + "px"; // jump to endPosition
return; // exit function
}
box.style.left = position + "px"; // move to the new position
}
var handler = setInterval(move, 1000/fps); // run move() every 16~ millisecond
body {
background: gainsboro;
}
#box {
width: 100px;
height: 100px;
background: white;
box-shadow: 1px 1px 1px rgba(0,0,0,.2);
position: absolute;
left: 0;
}
<div id="box"></div>
では、イージングを追加しましょう。linear
(イージングなし)を使用して簡単に始めます。上記と同じアニメーションになりますが、アプローチが異なります。今回は、位置変数を直接変更しません。変更するのは時間です。
function linear(time, begin, change, duration) {
return change * (time / duration) + begin;
}
まず、パラメータについて説明しましょう。
time
:経過時間begin
: プロパティの初期値 (幅、左、マージン、不透明度など)change
: 変位、(終了値 - 開始値)duration
: アニメーションにかかる合計時間time
とduration
直接関係しています。2 秒のアニメーションがある場合は、time
それを増やしてイージング関数に渡しますlinear
。この関数は、ボックスが指定された時間にその位置にあるべきであることを示す位置を返します。
ボックスを 0 から 100 まで 2 秒で移動するとします。ボックスの位置を取得したい場合、たとえば 700 ミリ秒linear
で、次の方法で関数を呼び出します。
linear(0.7, 0, 100, 2);
戻り35
ます。アニメーション開始から 700 ミリ秒後、ボックスの位置は 35px になります。これを実際に見てみましょう。
var box = document.getElementById("box");
var fps = 60;
var duration = 2; // seconds
var iterations = fps * duration; // 120 frames
var startPosition = 0; // left end of the screen
var endPosition = window.innerWidth - box.clientWidth; // right end of the screen
var distance = endPosition - startPosition; // total distance
var timeIncrement = duration / iterations;
var position = 0;
var time = 0;
function move() {
time += timeIncrement;
position = linear(time, startPosition, distance, duration);
if (position >= endPosition) {
clearInterval(handler);
box.style.left = endPosition + "px";
return;
}
box.style.left = position + "px";
}
var handler = setInterval(move, 1000/fps);
function linear(time, begin, change, duration) {
return change * (time / duration) + begin;
}
body {
background: gainsboro;
}
#box {
width: 100px;
height: 100px;
background: white;
box-shadow: 1px 1px 1px rgba(0,0,0,.2);
position: absolute;
left: 0;
}
<div id="box"></div>
このコードで注意が必要な部分は次のとおりです。
var timeIncrement = duration / iterations;
var time = 0;
function move() {
time += timeIncrement;
position = linear(time, startPosition, distance, duration);
// ...
最初のアニメーションでは、位置変数を直接変更しました。一定の位置増分値が必要でした。計算方法は ですposIncrement = distance / iterations
。イージングでは、位置変数を変更するのではなく、時間変数を変更します。したがって、時間増分値が必要です。位置の増分と同じ方法で計算しますが、今回は で割りduration
ますiterations
。時間の増分に応じて時間を増やし、その時間をイージング関数に渡します。イージング関数は、ボックスが占めるべき次の位置を返します。
total distance / iterations (frames) = position change per frame
total duration / iterations (frames) = time change per frame
ここにいくつかの目のグラフがあります。
最後に、easeInOutQuad の例です。
var box = document.getElementById("box");
var fps = 60;
var duration = 2; // seconds
var iterations = fps * duration; // 120 frames
var startPosition = 0; // left end of the screen
var endPosition = window.innerWidth - box.clientWidth; // right end of the screen
var distance = endPosition - startPosition; // total distance
var timeIncrement = duration / iterations;
var time = 0;
var position = 0;
function move() {
time += timeIncrement;
position = easeInOutQuad(time, startPosition, distance, duration);
if (position >= endPosition) {
clearInterval(handler);
box.style.left = endPosition + "px";
return;
}
box.style.left = position + "px";
}
var handler = setInterval(move, 1000 / fps);
function easeInOutQuad(t, b, c, d) {
if ((t /= d / 2) < 1) {
return c / 2 * t * t + b;
} else {
return -c / 2 * ((--t) * (t - 2) - 1) + b;
}
}
body {
background: gainsboro;
}
#box {
width: 100px;
height: 100px;
background: white;
box-shadow: 1px 1px 1px rgba(0,0,0,.2);
position: absolute;
left: 0;
}
<div id="box"></div>
これは、ある状態から別の状態へのプロパティ (サイズ、形状、場所) の遷移です。
jquery ui によって提供されるイージング関数を説明するいくつかのきちんとした小さなグラフを次に示します。