0

まず最初に、2つのことを述べたいと思います
。1つ:私のコードは完璧ではありません(特に評価部分)-しかし、私は自分自身のために何かを試し、jQueryアニメーション関数を複製できるかどうかを確認したかったので、許してください「悪い」慣行です。jQueryを使用することを提案しないでください。実験したかったのです。
2:このコードはまだ完成していないので、何がうまく機能しないのかを知りたかっただけです。

したがって、入力した期間パラメータが15秒であるのに対し、アニメーションは約12秒間実行されます。何が問題なのですか?

function animate(elem, attr, duration){
  if(attr.constructor === Object){//check for object literal
    var i = 0;
    var cssProp = [];
    var cssValue = [];
    for(key in attr) {
          cssProp[i] =  key;
          cssValue[i] = attr[key];
    }
    var fps = (1000 / 60);
    var t = setInterval(function(){
      for(var j=0;j<cssProp.length;j++){
        if(document.getElementById(elem).style[cssProp[j]].length == 0){
          //asign basic value in css if the object dosn't have one.
         document.getElementById(elem).style[cssProp[j]]= 0;
        }
        var c = document.getElementById(elem).style[cssProp[j]];
        //console.log(str +" | "+c+"|"+cssValue[j]);
        if(c > cssValue[j]){
            document.getElementById(elem).style[cssProp[j]] -= 1/((duration/fps)*(c-cssValue[j]));
        }else if(c < cssValue[j]){
            document.getElementById(elem).style[cssProp[j]] += 1/((duration/fps)*(c-cssValue[j]));
        }else if(c == cssValue[j]){
            window.clearInterval(t);
        }
      }
    },fps);
  }
}
  animate('hello',{opacity:0},15000);

html:

  <p id="hello" style="opacity:1;">Hello World</p>

注:問題があると思います

(duration / fps)*(c-cssValue [j])

setInterval(fps変数)の一部または/および間隔。


よろしくお願いします。

4

2 に答える 2

5

私はそれをリファクタリングして理解するつもりはありません、それはかなり不安定だからです。そうは言っても...いくつかのこと。

アニメーションの進行状況を知らせるために、アニメーション化する値に依存しないでください

一般的に、あなたのアプローチは不健全です。自分で進捗状況を追跡することをお勧めします。また、あなたのアプローチの結果として、あなたの数学はそれがあまりにも一生懸命に努力しているように見えます、そしてはるかに単純であるはずです。

このように考えてください。アニメーションの値が最終位置にあることを示しているように見えるときではなく、時間が経過したときにアニメーションが完了します。

インクリメントしない、設定する

浮動小数点の計算は不正確であり、このように繰り返し加算を累積すると、浮動小数点エラーも累積されます。また、進行状況を追跡するためにいくつかの変数を作成する方がはるかに読みやすく、計算に使用できます。

animatedValue += changeOnThisFrame // BAD!
animatedValue = valueOnThisFrame   // GOOD!

ポジティブ/ネガティブな条件付きダンスをしないでください

それが判明し、10 + 10実際10 - (-10)には同じことです。つまり、いつでも値を追加できますが、変化率は負または正になる可能性があり、値は適切な方向にアニメーション化されます。

タイムアウトと間隔は正確ではありません

実際には、 fnsetTimeout(fn, 50)が少なくとも50ミリ秒後に呼び出されるようにスケジュールすることを意味します。これらの50ms後に実行する次のJS実行ループは関数を実行するため、完全に正確であると信頼することはできません。

とはいえ、通常は数ミリ秒以内です。ただし、60fpsはフレームで約16msであり、そのタイマーは実際には16〜22msの可変時間で起動する可能性があります。そのため、フレームレートに基づいて計算を行う場合、実際の経過時間とはまったく一致しません。

複雑な数学をリファクタリングする

ここでこの線を分解するのは難しいでしょう。

document.getElementById(elem).style[cssProp[j]] -= 1/((duration/fps)*(c-cssValue[j]));

なぜもっと複雑なのか、ここで何が起こっているのかを簡単に理解できるように分割してください。この行を単独でリファクタリングすると、次のようになります。

var style = document.getElementById(elem).style;
var changeThisFrame = duration/fps;
var someOddCalculatedValue = c-cssValue[j];
style[cssProp[j]] -= 1 / (changeThisFrame * someOddCalculatedValue);

これを行うと、数学の各式が何を意味し、それが何のためにあるのかが明確になります。そして、あなたがここでそれをしなかったので、私はなぜc-cssValue[j]そこにあったのか、そしてそれが何を表しているのか疑問に思うのに非常に苦労しました。

簡単な例

これはあなたが持っているものよりも能力が劣りますが、あなたがとるべきアプローチを示しています。アニメーションの開始時間を使用して、アニメーションの完成度、開始場所、進行場所に応じて、完璧な値を作成します。現在のアニメーション値を使用して何かを決定することはなく、アニメーションの全長を実行することが保証されています。

var anim = function(elem, duration) {

    // save when we started for calculating progress
    var startedAt = Date.now();

    // set animation bounds
    var startValue = 10;
    var endValue   = 200;

    // figure out how much change we have over the whole animation
    var delta = endValue - startValue;

    // Animation function, to run at 60 fps.
    var t = setInterval(function(){

        // How far are we into the animation, on a scale of 0 to 1.
        var progress = (Date.now() - startedAt) / duration;

        // If we passed 1, the animation is over so clean up.
        if (progress > 1) {
            alert('DONE! Elapsed: ' + (Date.now() - startedAt) + 'ms');
            clearInterval(t);
        }

        // Set the real value.
        elem.style.top = startValue + (progress * delta) + "px";

    }, 1000 / 60);
};

anim(document.getElementById('foo'), 5000);
​

JSFiddle: http: //jsfiddle.net/DSRst/

于 2012-06-15T00:10:56.720 に答える
3

setInterval正確な合計タイミングには使用できません。JS はシングル スレッドであり、複数のものが 1 つのスレッドでサイクルを競合するため、次のインターバル呼び出しが時間通りに行われる、または N インターバルが正確な時間を消費するという保証はありません。

代わりに、ほとんどすべてのアニメーション ルーチンが現在の時間を取得し、システム クロックを使用して合計時間を測定します。一般的なアルゴリズムは、開始時刻を取得し、目的の終了時刻 (開始時刻 + 期間) を計算することです。次に、これまでと同様に、予想されるステップ値と反復回数を計算します。次に、各ステップで、残りの残り時間と残りのステップ値を再計算します。このようにして、アニメーションが常に正確に (またはほぼ正確に) 時間どおりに終了し、常に正確に最終位置に到達するようにします。アニメーションが理想的な軌道から遅れると、アニメーションは自己修正し、残りのステップで少しだけ動きます。何らかの理由 (丸めエラーなど) で先に進んだ場合は、ステップ サイズをダイヤル バックし、同様に時間通りに最終位置に到達します。

また、ブラウザーが常に非常に小さなタイミング量をサポートしているわけではないことも知っておく必要があるかもしれません。各ブラウザには、タイマー操作に許可される最小時間があります。タイマーの最小レベルに関する記事を次に示します。

これは、トゥイーンに関する記事です (デュレーションに正確に適合するようにステップを継続的に再計算するプロセス)。

また、いくつかのライブラリ (jQuery、YUI、またはその他のライブラリ) でアニメーションを実行するためのコードを確認することをお勧めします。それらはすべて、トゥイーン、イージング関数など、非常に汎用的な方法でこれがどのように行われるかを示しているからです。など...

于 2012-06-14T23:51:08.697 に答える