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

Ilmari Heikkinen

अगर 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 एफ़पीएस (फ़्रेम प्रति सेकंड) पाने में मदद करता है और 60 FPS (फ़्रेम प्रति सेकंड) का मतलब है हर फ़्रेम के लिए 16.7 मि॰से॰. हालांकि, इंटिजर मिलीसेकंड में मेज़र करने का मतलब है कि हमें जो भी डेटा देखना और टारगेट करना है उसके लिए हमारे पास 1/16 की सटीक जानकारी है.

16 मि॰से॰ बनाम 16 इंटिजर मि॰से॰ ग्राफ़ की तुलना.

जैसा कि ऊपर देखा जा सकता है, नीला बार यह दिखाता है कि नया फ़्रेम (60fps पर) पेंट करने से पहले, आपको अपने सभी काम ज़्यादा से ज़्यादा कितने समय तक करने होंगे. हो सकता है कि 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 में लागू करने की योजना बना रहे हैं, इसलिए अगर आपको पहले से ही इस कॉलबैक पैरामीटर का फ़ायदा मिल रहा है, तो अपना कोड अपडेट करना न भूलें!