44

たとえば、オブジェクトがX1座標からX2座標に等時間間隔でSステップにわたって移動するEase-OutアニメーションとEase-Inアニメーションを実行しているとします。この動きのX座標を計算する式を提案できる人はいますか?

4

6 に答える 6

84

個人的には、[0;で時間を取得する関数を使用したいと思います。1]そして[0;に値を出力します。1]、結果を任意のタイプ(2Dベクトル、3Dベクトルなど)に適用できるようにします。

解決策1

二次イージングイン/アウトの場合、曲線は次の値に応じて2つの異なる関数に分けられますt

  • t<= 0.5の場合: f(x) = 2 * x * x[0; 0.5]のxを使用(グラフ
  • t> 0.5の場合: f(x) = 2 * x * (1 - x) + 0.5xが[0; 0.5]の場合(グラフ

グラフは次のとおりです。

グラフ-パート1
グラフ-パート2

2番目の関数も[0;0.5]にありますがt、使用を開始すると> 0.5になるため、0.5減らす必要がありtます。

これは、Cでの結果です。

float InOutQuadBlend(float t)
{
    if(t <= 0.5f)
        return 2.0f * t * t;
    t -= 0.5f;
    return 2.0f * t * (1.0f - t) + 0.5f;
}

解決策2(ベジェ)

もう1つの興味深いブレンド曲線は、ベジェによって与えられたものです。これには、非常に最適化されるという利点があります(ifがない場合)。これがWolframの曲線です。

ベジェ曲線

そしてここにCコードがあります:

float BezierBlend(float t)
{
    return t * t * (3.0f - 2.0f * t);
}

解決策3(パラメトリック関数)

@DannyYaroslavskiによって提案された別の方法は、ここで提案された単純な式です。

それはパラメトリックであり、素晴らしいイン/アウトの加速と減速を取得します。

alpha = 2の場合、次の関数が得られます。

曲線

これはCで次のように変換されます:

float ParametricBlend(float t)
{
    float sqt = t * t;
    return sqt / (2.0f * (sqt - t) + 1.0f);
}

編集1: @DannyYaroslavskiからソリューション3を追加
編集2:ソリューション1のより良い説明
編集3:すべてのソリューションにグラフを追加

于 2014-09-08T18:14:40.083 に答える
45

二次方程式はどこで簡単になりますか:

t=現在の時刻
b=開始値
c=値の変化
d=期間

 function (float time, float startValue, float change, float duration) {
     time /= duration / 2;
     if (time < 1)  {
          return change / 2 * time * time + startValue;
     }

     time--;
     return -change / 2 * (time * (time - 2) - 1) + startValue;
 };

ソース: http: //gizma.com/easing/

于 2012-11-19T21:00:17.567 に答える
1

上記のすべてのソリューションには、使用例がありません。

ここで良い解決策を見つけました:

 function animate({timing, draw, duration}) {

  let start = performance.now();

  requestAnimationFrame(function animate(time) {
    // timeFraction goes from 0 to 1
    let timeFraction = (time - start) / duration;
    if (timeFraction > 1) timeFraction = 1;

    // calculate the current animation state
    let progress = timing(timeFraction)

    draw(progress); // draw it

    if (timeFraction < 1) {
      requestAnimationFrame(animate);
    }

  });
}

使用例:

animate({
  duration: 1000,
  timing(timeFraction) { // here you can put other functions
    return timeFraction;
  },
  draw(progress) {
    elem.style.width = progress * 100 + '%';
  }
});

その他の機能:

function quad(timeFraction) {
  return Math.pow(timeFraction, 2)
}

詳細はこちら

于 2019-09-27T10:31:56.067 に答える
0

同じ問題が発生しました。チャートをアニメーション化したかったの(Ease in-out)です。

ブレインストームは私に2つの方法を与えました:

1)トリゴノメトリック式。最初に、私は書いたy=(sin(x/π*10-π/2)+1)/2、どのアナログはsin^2((5*x)/π)

float TrygoEase (float x) {
    float y=(float)Math.pow(Math.sin(5*x/Math.PI),2);
    return y;
}

2)2つの放物線。難しくはありませんでした。私はちょうどで、そしてで使用y=2*x*xしました[0;0.5]y=-2(x-1)^2+1[0.5;1]

float ParabolEase(float x) {
    float y=2*x*x;
    if(x>0.5f){
        x-=1;
        y=-2*x*x+1;
    }
    return y;
} 

この方法を使用してx=[0;1]、何が返されるかについても説明しy=[0;1]ます。

これで、このグラフを比較できます。

ここに画像の説明を入力してください

于 2018-06-22T06:39:48.370 に答える
0

これは、Creakによってリンクされたこの一般的なソリューションに従って、曲率の量を引数として持つバージョンです。

/*
* applyCurve: apply an S-curve to an input value.
* The highest positive curvature will result in a step from 0 to 1,
* the most negative curvature will result in a constant of 0.5.
*
* progress: the input value between 0 and 1,
* curvature: the amount of curvature between -1 and 1.
*  Negative values curve the other way, 0 applies no curvature.
*/

double applyCurve(double progress, double curvature) {
    assert(progress >= 0.0 && progress <= 1.0);
    assert(curvature >= -1.0 && curvature <= 1.0);

    if (curvature >= 0.0) {
        if (curvature > 0.99999) return progress > 0.5 ? 1.0 : 0.0;

        float exp = 1.0 / (1.0 - curvature); // find s-curve exponent
        return pow(progress, exp) / (pow(progress, exp) + pow(1.0 - progress, exp)); // apply s-curve
    } else {
        if (curvature < -0.99999) return 0.5;

        float exp = 1.0 + curvature; // find s-curve exponent
        return pow(progress, exp) / (pow(progress, exp) + pow(1.0 - progress, exp)); // apply s-curve
    }
}
于 2020-05-12T08:02:07.377 に答える
0

このバージョンでは、イーズインおよびイーズアウト関数(EaseInおよびEaseOut)を使用できます。両方の関数は、0から1の間の時間値パラメーターを取り、0から1の間の緩和された時間値を返す必要があります。

float EaseInOut(float t)
{
    if (t <= 0.5f)
    {
        return EaseIn(t * 2) * 0.5f;
    }
    else
    {
        t -= 0.5f;
        return (EaseOut(t * 2) * 0.5f) + 0.5f;
    }
}
于 2021-04-30T13:06:39.243 に答える