2013-08-01 13 views
10

javascript、jQueryなどの手段を使用して、CSS3 @keyframesアニメーションの現在のアニメーションパーセンテージを取得/設定できますか?現在の@keyframes%/変更キーフレームの取得/設定

というと.spinと呼ばれるクラスがあり、単にspinと呼ばれるキーフレームを使用して円で回転しているとします。私はまた、オリジナルのアニメーションを変更することに興味が空

  • $('.spin').css('animation')$('.spin').css('animation: spin')を使用して、アニメーションの現在の割合値を取得しようとしました、そして夫婦他の方法が、それら全てが警告している

    1. それぞれの定義済みのキーフレーム%で、私は$('.spin').css('animation', '..new definition here...')$('.spin').css('spin', '50%', '...new definition here...)のようなものを試してみました。

  • 答えて

    12

    私は、私のCSS3で純粋なjavascriptを使用したかったものを大まかに達成しました。

    私の実験では、これらの目的を達成するための方法を考え出すために、小さな円形の周りを回転する基本的なCSS3アニメーションを作成しました。私の目標は、ボタンがクリックされたときに、以下のsetIntervalを使用して、私は単に現在の割合を近似したアニメーションのパーセント値を得るための最初の目標を達成するために、新しい場所

    にアニメーションの起源を変更することでした近似された現在のパーセントを表示します。

    • カウンタは、別のタブをクリックしたときに実行し続けるので、それが原因完璧ではないですが、これは、このソリューションのアニメーション(milliseconds/100)

      var result = document.getElementById('result'), currentPercent = 0; 
      var showPercent = window.setInterval(function() { 
          if(currentPercent < 100) 
          { 
          currentPercent += 1; 
          } 
          else { 
          currentPercent = 0; 
          } 
          result.innerHTML = currentPercent; 
      }, 40); 
      

      ノートの期間に対応するために40ミリ秒毎に実行されますアニメーションが停止して同期しなくなる

    • 最後にクリックしてからボタンを長くクリックするとエラーになります。明らかに、私はより多くの完璧なソリューションのためにどこにでも見えたが、まだ

    のような一つを思い付くことができなかったのsetIntervalは少し長いアニメーションよりも動作しますので、彼らは少なく、各反復

  • を同期になりますアニメーションの%値の新しい定義を設定するという第2の目標を達成するには、もっと複雑な解決方法が必要でした。記事やウェブページ(重要なもの下記参照)の数十を通して注いだ後、私は次の解決策を考え出すために管理:ジャバスクリプトの各部分が何をしているかを説明するコメントを含む

    var circle = document.getElementById('circle'), 
        button = document.getElementById('button'); 
    var result = document.getElementById('result'), 
        totalCurrentPercent = 0, 
        currentPercent = 0; 
    var showPercent = window.setInterval(function() { 
        if(currentPercent < 100) 
        { 
        currentPercent += 1; 
        } 
        else { 
        currentPercent = 0; 
        } 
        result.innerHTML = currentPercent; 
    }, 40); 
    function findKeyframesRule(rule) { 
        var ss = document.styleSheets; 
        for (var i = 0; i < ss.length; ++i) { 
         for (var j = 0; j < ss[i].cssRules.length; ++j) { 
          if (ss[i].cssRules[j].type == window.CSSRule.WEBKIT_KEYFRAMES_RULE && ss[i].cssRules[j].name == rule) { return ss[i].cssRules[j]; } 
         } 
        } 
        return null; 
    } 
    function change(anim) { 
        var keyframes = findKeyframesRule(anim), 
         length = keyframes.cssRules.length; 
        var keyframeString = []; 
        for(var i = 0; i < length; i ++) 
        { 
        keyframeString.push(keyframes[i].keyText); 
        } 
        var keys = keyframeString.map(function(str) { 
        return str.replace('%', ''); 
        }); 
        totalCurrentPercent += currentPercent; 
        if(totalCurrentPercent > 100) 
        { 
        totalCurrentPercent -= 100; 
        } 
        var closest = getClosest(keys); 
        var position = keys.indexOf(closest), 
         firstPercent = keys[position]; 
        for(var i = 0, j = keyframeString.length; i < j; i ++) 
        { 
        keyframes.deleteRule(keyframeString[i]); 
        } 
        var multiplier = firstPercent * 3.6; 
        keyframes.insertRule("0% { -webkit-transform: translate(100px,100px) rotate(" + (multiplier + 0) + "deg) translate(-100px,-100px) rotate(" + (multiplier + 0) + "deg); background-color:red; }"); 
        keyframes.insertRule("13% { -webkit-transform: translate(100px,100px) rotate(" + (multiplier + 45) + "deg) translate(-100px,-100px) rotate(" + (multiplier + 45) + "deg); }"); 
        keyframes.insertRule("25% { -webkit-transform: translate(100px,100px) rotate(" + (multiplier + 90) + "deg) translate(-100px,-100px) rotate(" + (multiplier + 90) + "deg); }"); 
        keyframes.insertRule("38% { -webkit-transform: translate(100px,100px) rotate(" + (multiplier + 135) + "deg) translate(-100px,-100px) rotate(" + (multiplier + 135) + "deg); }"); 
        keyframes.insertRule("50% { -webkit-transform: translate(100px,100px) rotate(" + (multiplier + 180) + "deg) translate(-100px,-100px) rotate(" + (multiplier + 180) + "deg); }"); 
        keyframes.insertRule("63% { -webkit-transform: translate(100px,100px) rotate(" + (multiplier + 225) + "deg) translate(-100px,-100px) rotate(" + (multiplier + 225) + "deg); }"); 
        keyframes.insertRule("75% { -webkit-transform: translate(100px,100px) rotate(" + (multiplier + 270) + "deg) translate(-100px,-100px) rotate(" + (multiplier + 270) + "deg); }"); 
        keyframes.insertRule("88% { -webkit-transform: translate(100px,100px) rotate(" + (multiplier + 315) + "deg) translate(-100px,-100px) rotate(" + (multiplier + 315) + "deg); }"); 
        keyframes.insertRule("100% { -webkit-transform: translate(100px,100px) rotate(" + (multiplier + 360) + "deg) translate(-100px,-100px) rotate(" + (multiplier + 360) + "deg); }"); 
        circle.style.display = "inherit"; 
        circle.style.webkitAnimationName = anim; 
        window.clearInterval(showPercent); 
        currentPercent = 0; 
        showPercent = self.setInterval(function() { 
        if(currentPercent < 100) 
        { 
         currentPercent += 1; 
        } 
        else { 
         currentPercent = 0; 
        } 
        result.innerHTML = currentPercent; 
        }, 40); 
    } 
    button.onclick = function() { 
        circle.style.webkitAnimationName = "none"; 
        circle.style.display = "none"; 
        setTimeout(function() { 
         change("rotate"); 
        }, 0); 
    } 
    function getClosest(keyframe) { 
        var curr = keyframe[0]; 
        var diff = Math.abs (totalCurrentPercent - curr); 
        for (var val = 0; val < keyframe.length; val++) { 
        var newdiff = Math.abs(totalCurrentPercent - keyframe[val]); 
        if (newdiff < diff) { 
         diff = newdiff; 
         curr = keyframe[val]; 
        } 
        } 
        return curr; 
    } 
    

    Check out the experiment itself here

    このソリューションで注:

  • できるだけ非ハードコードされたとして

    • 私はそれが動作変更機能を作ってみましたそうアニメーションにより%の定義を追加することになる、あるアニメーションから他への遷移は、アニメーションの現在%までがアニメーションの最寄り%値を塞ぐようにのみように滑らかである現在@keyvalueパーセンテージ
    • を近似する大丈夫問題の解決策を思い付くしようとする過程で

    それがさらに滑らかに、私が見つけたこれらの便利なリソース:

    • RussellUresti's answer in this SO postcorresponding exampleはかなり影響を与えたと大幅に私の最終的な解決を支援しました
    • を入力して、配列の値に基づいて、最も近い値を取得するには、私は(私はそれを自分自身を使用していませんでしたが、非常によく似を達成するように見えた、
    • This plugin(ありがとう)this SO postにpaxdiabloの方法を使用し、一見ではない、非常にかかわらず、 jQueryの

    のようにカスタマイズ可能な)効果--- EDIT ---

    あなただけのCSSがを移行またはあなただけの代わりにトランジションを使用するようにアニメーションを変更することができます使用している場合は、を使用することができます210。あなたは、トランジションによって変更する属性をコピーしたものに変更する属性に属性を設定し、それをアニメーション化するクラスを除去することによって、移行を一時停止することができます。あなたが最初のクリックをアニメーション化する必要があります一時停止/アニメーション化するために、同じオブジェクトを使用している場合はもちろん、それに次のクリックを一時停止します。あなたは簡単に、純粋なJavaScriptの同等の操作を行うことができ、同様

    注:とは対照的に、あなたがdiv #defaultID.animationClass {ような何か別名、jQueryのセレクタよりもアニメーションクラスのためのより平らにセレクタを持っていない限り CSS変更属性で!importantが必要ですただ#defaultID.animationClass {#defaultID#defaultID.animationClass一のレベルの両方であるので、この例では、このトピックに関する詳細は!important

    --Another Edit--

    を必要とする、my post on CSS-Tricks

    チェックアウト
  • 関連する問題