إذا كنت تستخدم requestAnimationFrame
، يمكنك الاستفادة من مزامنة رسوماتك مع معدّل تحديث الشاشة، ما يؤدي إلى إنشاء رسوم متحركة بدقة عالية قدر الإمكان. بالإضافة إلى ذلك، يمكنك توفير طاقة البطارية وضوضاء مروحة وحدة المعالجة المركزية للمستخدمين عند تبديلهم إلى علامة تبويب أخرى.
مع ذلك، سيكون هناك تغيير على جزء من واجهة برمجة التطبيقات على وشك أن يحدث. يتغيّر الطابع الزمني الذي يتم إدخاله في دالة معاودة الاتصال من طابع زمني نموذجي يشبه Date.now()
إلى قياس عالي الدقة للنقطة العائمة منذ فتح الصفحة. إذا استخدمت هذه القيمة، يجب تعديل الرمز بناءً على التوضيح أدناه.
للتوضيح، إليك ما أقصده:
// assuming requestAnimationFrame method has been normalized for all vendor prefixes..
requestAnimationFrame(function(timestamp){
// the value of timestamp is changing
});
إذا كنت تستخدم requestAnimFrame
العنصر الوسيط المقدَّم هنا، هذا يعني أنّك لا تستخدم قيمة الطابع الزمني. لا داعي للقلق. :)
السبب
لماذا؟ يساعدك وضع "معدل عرض اللقطات المتغير" في الحصول على معدل مثالي يبلغ 60 لقطة في الثانية، ويعادل هذا المعدل 16.7 ملي ثانية لكل لقطة. ولكن القياس باستخدام عدد صحيح من المللي ثانية يعني أنّ لدينا دقة 1/16 لكل ما نريد رصده واستهدافه.
كما هو موضّح أعلاه، يمثّل الشريط الأزرق الحد الأقصى للوقت المتاح لك لتنفيذ جميع أعمالك قبل رسم لقطة جديدة (بسرعة 60 لقطة في الثانية). من المحتمل أنّك تُجري أكثر من 16 إجراءً، ولكن باستخدام الكسور الصحيحة من الثانية، لا يمكنك جدولة الإجراءات وقياسها إلا من خلال هذه الخطوات الكبيرة جدًا. هذا ليس جيدًا بما يكفي.
يحلّ الموقّت عالي الدقة هذه المشكلة من خلال تقديم رقم أكثر دقة:
Date.now() // 1337376068250
performance.now() // 20303.427000007
يتوفّر حاليًا الموقّت عالي الدقة في Chrome باسم window.performance.webkitNow()
، وهذه القيمة تساوي بشكل عام قيمة الوسيطة الجديدة التي تم تمريرها إلى دالة الاستدعاء في rAF. بعد أن تصبح المواصفات متوافقة مع المعايير، ستتم إزالة البادئة وستصبح الطريقة متاحة من خلال performance.now()
.
ستلاحظ أيضًا أنّ القيمتَين أعلاه تختلفان بعدّة orders of magnitude. 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));
}
يمكنك بسهولة تعديل هذا الخطأ من خلال إضافة startTime
وnow
لاستخدام window.performance.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 عامًا. ولكن لا يمكننا اختبار ما إذا كان رقمًا عشريًا (بدلاً من تقريبه إلى عدد صحيح). اطلب عددًا كافيًا من المؤقتات العالية الدقة، وستحصل على قيم صحيحة في مرحلة ما.
نخطّط لطرح هذا التغيير في الإصدار 21 من Chrome، لذا إذا كنت تستفيد حاليًا من مَعلمة callback هذه، احرص على تعديل الرمز.