requestAnimationFrame API - अब सब-मिलीसेकंड सटीक जानकारी के साथ

इल्मारी हेकिनेन

अगर आप requestAnimationFrame का इस्तेमाल करते आ रहे हैं, तो आपको स्क्रीन की रीफ़्रेश दर के साथ अपने पेंट को सिंक करके अच्छा लगा है. इसकी वजह से, सबसे हाई फ़िडेलिटी वाले ऐनिमेशन मिलते हैं. साथ ही, इससे आपके उपयोगकर्ता किसी दूसरे टैब पर स्विच करने पर, सीपीयू के पंखे की आवाज़ और बैटरी पावर की बचत करते हैं.

हालांकि, इस एपीआई के हिस्से में बदलाव होने वाला है. आपके कॉलबैक फ़ंक्शन में भेजा गया टाइमस्टैंप, Date.now() जैसे सामान्य टाइमस्टैंप से, पेज खुलने के बाद से फ़्लोटिंग पॉइंट मिलीसेकंड के हाई रिज़ॉल्यूशन मेज़रमेंट में बदल रहा है. अगर इस वैल्यू का इस्तेमाल किया जाता है, तो आपको अपना कोड अपडेट करना होगा. इसके लिए, नीचे दी गई जानकारी का इस्तेमाल किया जा सकता है.

आपकी जानकारी के लिए बता दें कि मैं यहां इस बारे में बात कर रहा हूं:

// assuming requestAnimationFrame method has been normalized for all vendor prefixes..
requestAnimationFrame(function(timestamp){
    // the value of timestamp is changing
});

अगर यहां दिए गए सामान्य requestAnimFrame शिम का इस्तेमाल किया जा रहा है, तो इसका मतलब है कि टाइमस्टैंप वैल्यू का इस्तेमाल नहीं किया जा रहा है. आप हुक से बाहर हैं. :)

क्यों शुरू करें?

ऐसा क्यों हो रहा है? वेल rAF आपको आदर्श 60 FPS (फ़्रेम प्रति सेकंड) पाने में मदद करता है. साथ ही, 60 FPS (फ़्रेम प्रति सेकंड) का अनुवाद, हर फ़्रेम के लिए 16.7 मि॰से॰ हो जाता है. हालांकि, पूर्णांक मिलीसेकंड से मेज़र करने का मतलब है कि हमें हर उस चीज़ के लिए 1/16 की सटीक जानकारी मिलती है जिसे हम मॉनिटर और टारगेट करना चाहते हैं.

16 मि॰से॰ बनाम 16 पूर्णांक एमएस वाले ग्राफ़ की तुलना.

जैसा कि ऊपर देखा जा सकता है, नीला बार यह दिखाता है कि नए फ़्रेम (60 FPS पर) को पेंट करने से पहले, आपको अपने सभी काम करने में ज़्यादा से ज़्यादा कितना समय लगता है. शायद आप 16 से ज़्यादा काम कर रहे हों, लेकिन पूर्णांक मिलीसेकंड के साथ आपके पास सिर्फ़ उन बहुत ही ज़रूरी बढ़ोतरी को शेड्यूल करने और मापने की क्षमता होती है. यह काफ़ी नहीं है.

हाई रिज़ॉल्यूशन टाइमर ज़्यादा सटीक फ़ोटो देकर इसे हल करता है:

Date.now()         //  1337376068250
performance.now()  //  20303.427000007

फ़िलहाल, हाई रिज़ॉल्यूशन वाला टाइमर Chrome में window.performance.webkitNow() के तौर पर उपलब्ध है. आम तौर पर, यह वैल्यू rAF कॉलबैक में दी गई नई आर्ग्युमेंट वैल्यू के बराबर होती है. जब निर्देशों में आगे स्टैंडर्ड के हिसाब से बदलाव किए जाएंगे, तो तरीका प्रीफ़िक्स को हटा देगा और performance.now() के ज़रिए उपलब्ध हो जाएगा.

आपको यह भी दिखेगा कि ऊपर दी गई दो वैल्यू, बहुत ज़्यादा अलग-अलग हैं. किसी पेज के लोड होने के शुरू होने के बाद से, performance.now() फ़्लोटिंग पॉइंट मिलीसेकंड का मेज़रमेंट होता है. आम तौर पर, यह performance.navigationStart के हिसाब से लोड होता है.

इस्तेमाल किया जा रहा है

क्रॉप की जाने वाली मुख्य समस्या ऐनिमेशन लाइब्रेरी है, जो इस डिज़ाइन पैटर्न का इस्तेमाल करती हैं:

function MyAnimation(duration) {
    this.startTime = Date.now();
    this.duration = duration;
    requestAnimFrame(this.tick.bind(this));
}
MyAnimation.prototype.tick = function(time) {
    var now = Date.now();
    if (time > now) {
        this.dispatchEvent("ended");
        return;
    }
    ...
    requestAnimFrame(this.tick.bind(this));
}

इसे ठीक करने के लिए एक बार में बदलाव करना बहुत आसान है... window.performance.now() का इस्तेमाल करने के लिए, startTime और now को बढ़ाएं.

this.startTime = window.performance.now ?
                    (performance.now() + performance.timing.navigationStart) :
                    Date.now();

यह एक आसान तरीका है. इसमें प्रीफ़िक्स वाले now() तरीके का इस्तेमाल नहीं किया गया है. साथ ही, इसमें Date.now() के साथ काम करने की सुविधा है, जो IE8 में नहीं है.

सुविधा की पहचान

अगर आपने ऊपर दिए गए पैटर्न का इस्तेमाल नहीं किया है और सिर्फ़ यह पता करना है कि आपको किस तरह की कॉलबैक वैल्यू मिल रही है, तो इस तकनीक का इस्तेमाल किया जा सकता है:

requestAnimationFrame(function(timestamp){

    if (timestamp < 1e12){
        // .. high resolution timer
    } else {
        // integer milliseconds since unix epoch
    }

    // ...

if (timestamp < 1e12) पर जाकर यह देखना है कि हम कितनी बड़ी संख्या का सामना कर रहे हैं. तकनीकी रूप से यह गलत हो सकता है, लेकिन सिर्फ़ तब, जब कोई वेबपेज 30 सालों तक लगातार खुला रहता है. हालांकि, हम यह टेस्ट नहीं कर सकते कि यह फ़्लोटिंग पॉइंट नंबर है या नहीं, न कि किसी पूर्णांक पर. ज़रूरत के हिसाब से हाई रिज़ॉल्यूशन टाइमर मांगें और आपको कभी-कभी पूर्णांक वैल्यू मिल सकती हैं.

हम इस बदलाव को Chrome 21 में लागू करने जा रहे हैं. इसलिए, अगर पहले से ही इस कॉलबैक पैरामीटर का फ़ायदा लिया जा रहा है, तो अपने कोड को अपडेट करना न भूलें!