2013-08-01 5 views
10

प्राप्त करें/सेट करें जावास्क्रिप्ट, jQuery, या किसी अन्य माध्यम का उपयोग कर CSS3 @keyframes एनीमेशन के वर्तमान एनीमेशन प्रतिशत को प्राप्त/सेट करना संभव है?वर्तमान @keyframes प्रतिशत/बदलें keyframes

उदाहरण के लिए कहें div.spin नामक कक्षा के साथ कहता है जो केवल एक कीफ्रेम का उपयोग करके सर्कल में चारों ओर स्पिन करता है जिसे spin भी कहा जाता है।

  1. मैं एक जोड़े को अन्य तरीकों $('.spin').css('animation'), $('.spin').css('animation: spin') का उपयोग कर एनीमेशन की वर्तमान प्रतिशत मूल्य प्राप्त करने की कोशिश की है, और, लेकिन वे सभी चेतावनी खाली

  2. मैं भी मूल एनीमेशन बदलने में रुचि रखते कर रहा हूँ प्रत्येक पूर्वनिर्धारित कीफ्रेम% पर और मैंने $('.spin').css('animation', '..new definition here...') और $('.spin').css('spin', '50%', '...new definition here...) जैसी चीजों का कोई फायदा नहीं लिया है।

कोई विचार?

उत्तर

12

मैंने अपने CSS3 के साथ शुद्ध जावास्क्रिप्ट का उपयोग करके लगभग वही हासिल किया जो मैं चाहता था।

मेरे प्रयोग के लिए इन उद्देश्यों को करने के तरीके के साथ आने के लिए, मैंने एक छोटे से गोलाकार पथ के चारों ओर एक चक्र को घूर्णन करने वाली एक मूल CSS3 एनीमेशन बनाई। मेरा लक्ष्य करने के लिए, जब एक बटन क्लिक किया गया था, नए स्थान

को एनीमेशन के मूल को बदल निम्नलिखित setInterval का उपयोग कर एनीमेशन का प्रतिशत मूल्य प्राप्त करने का पहला गोल मैं बस वर्तमान प्रतिशत अनुमानित किया था प्राप्त करने के लिए , जो अनुमानित वर्तमान प्रतिशत प्रदर्शित करता है।

  • यह सही नहीं है की वजह से है क्योंकि काउंटर जब अन्य टैब क्लिक किया जाता है चल रहा है, लेकिन इसमें: यह हर 40 मिलीसेकंड इस समाधान पर एनीमेशन (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); 
    

    नोट की अवधि के साथ पत्र व्यवहार करने चलाता है एनीमेशन बंद हो जाता है, इसलिए वे अन-सिंक्रनाइज़ हो जाते हैं

  • यह भी दोषपूर्ण होता है जब बटन अंतिम क्लिक के बाद लंबे समय तक क्लिक किया जाता है। जाहिर है setInterval एक छोटा सा एनीमेशन से अधिक समय से चलता है, तो वे कम से कम synced बन प्रत्येक यात्रा
  • मैं हर जगह एक और अधिक सटीक समाधान के लिए देखा लेकिन अभी तक

के रूप में एक साथ आते हैं करने में असमर्थ हैं एनीमेशन के% मूल्य के लिए एक नई परिभाषा स्थापित करने के दूसरे लक्ष्य को प्राप्त करने के लिए इसमें थोड़ा अधिक जटिल समाधान लिया गया।लेख और वेब पृष्ठों (महत्वपूर्ण होते नीचे सूचीबद्ध) के दर्जनों के माध्यम से डालने का कार्य के बाद, मैं निम्नलिखित समाधान के साथ आने में कामयाब रहे:

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 post और corresponding example काफी प्रभावशाली था और बहुत अपने अंतिम समाधान सहायता प्राप्त
  • एक इनपुट और सरणी मूल्यों पर आधारित निकटतम मूल्य प्राप्त करने के लिए, मैं this SO post में paxdiablo की विधि का इस्तेमाल किया (धन्यवाद)
  • This plugin, जबकि मैं इसे अपने आप का उपयोग नहीं किया, एक बहुत ही इसी तरह की प्राप्त करने के लिए लग रहा था (हालांकि प्रतीत होता है काफी नहीं के रूप में अनुकूलन) jQuery में प्रभाव

--- संपादित करें ---

तुम सिर्फ सीएसएस संक्रमण उपयोग कर रहे हैं या आप अपने एनीमेशन सिर्फ बजाय संक्रमण का उपयोग करने के लिए बदल सकते हैं, तो आप उपयोग कर सकते हैं this simpler approach। आप संक्रमण द्वारा बदले गए गुणों की प्रतिलिपि बनाकर, उन बदले गए विशेषताओं में विशेषताओं को सेट करके संक्रमण को रोक सकते हैं, और उसके बाद इसे एनिमेट करने वाले वर्ग को हटा सकते हैं। बेशक यदि आप एक ही ऑब्जेक्ट को एनिमेट/पॉज़ करने के लिए उपयोग कर रहे हैं तो आपको पहले क्लिक को एनिमेट करने की आवश्यकता होगी, फिर इसे अगले क्लिक को रोक दें। आप आसानी से शुद्ध जावास्क्रिप्ट बराबर कर सकते हैं और साथ ही

नोट: सीएसएस बदल विशेषता में !important आवश्यक है जब तक आप jQuery चयनकर्ता से एनीमेशन वर्ग के लिए एक अधिक समतल चयनकर्ता के रूप में करने का विरोध किया है, div #defaultID.animationClass { की तरह कुछ उर्फ बस #defaultID.animationClass {। चूंकि #defaultID और #defaultID.animationClass दोनों एक स्तर है, इस उदाहरण इस विषय पर अधिक जानकारी के लिए !important

--Another Edit--

की आवश्यकता है, my post on CSS-Tricks

की जाँच
संबंधित मुद्दे