Web Animations: item.animate() متوفرة الآن في Chrome 36

برندان كيني
برندان كيني

كانت الرسوم المتحركة على الويب سابقًا مقاطعة لـ JavaScript، ولكن مع انتقال العالم إلى الجوّال، انتقلت الرسوم المتحركة إلى CSS لبنية التعريف والتحسينات التي تمكنت المتصفحات من إجراؤها باستخدامها. عند تحديد 60 لقطة في الثانية على الأجهزة الجوّالة، من المنطقي دائمًا عدم تجاوز الحدود التي تعرفها المتصفّحات لعرض المحتوى بكفاءة.

ويبدو أنّ استخدام المزيد من الأدوات يساعد على رفع كفاءة الصور المتحركة التي تعتمد على JavaScript، إلا أنّ الهدف الأساسي هو توحيد الصور المتحركة الموجزة والتوضيحية، والتي يستند فيها قرار كتابة الصور المتحركة إلى الرمز الأكثر وضوحًا، وليس إلى ما هو ممكن في شكل واحد وليس في الآخر.

تعمل Web Animations على الرد على هذه المكالمة، وقد وصل الجزء الأول منها إلى Chrome 36 في شكل element.animate(). تتيح لك هذه الوظيفة الجديدة إنشاء صورة متحركة بلغة JavaScript بشكلٍ كامل وتشغيلها بكفاءة مثل أي حركة CSS أو عملية نقل (في الواقع، اعتبارًا من الإصدار Chrome 34، يستخدم محرك "الرسوم المتحركة على الويب" نفسه جميع هذه الطرق).

البنية بسيطة، ويجب أن تكون أجزائها مألوفة لك إذا كنت قد كتبت من قبل نقل CSS أو رسوم متحركة:

element.animate([
    {cssProperty: value0},
    {cssProperty: value1},
    {cssProperty: value2},
    //...
], {
    duration: timeInMs,
    iterations: iterationCount,
    delay: delayValue
});

إنّ أكبر ميزة لهذه الميزة الجديدة هي التخلّص من الكثير من الأطوار المحرجة التي كان علينا سابقًا المرور بها للحصول على رسم متحرك سلس وخالٍ من المشاكل.

على سبيل المثال، بالنسبة إلى Santa Tracker في العام الماضي، أردنا استمرار تساقط الثلوج بشكل مستمر، وقرّرنا تحريكها باستخدام CSS حتى يتم عملها بكفاءة عالية.

ومع ذلك، أردنا اختيار الوضع الأفقي للثلج ديناميكيًا استنادًا إلى الشاشة والأحداث التي تدور في المشهد نفسه، وبالطبع لن يكون ارتفاع سقوط الثلج (ارتفاع نافذة المتصفح لدى المستخدم) معروفًا إلا بعد تشغيل الثلوج. نتيجةً لذلك، كان علينا استخدام عمليات انتقال CSS، إذ إنّ عملية إنشاء صور متحركة بتنسيق CSS في وقت التشغيل تزداد تعقيدًا بسرعة (وتتسبّب مئات رقاقات الثلج في تطبيق مئات قواعد التصميم الجديدة).

ولذلك، اعتمدنا النهج التالي، الذي يجب أن يكون مألوفًا:

snowFlake.style.transform = 'translate(' + snowLeft + 'px, -100%)';
// wait a frame
snowFlake.offsetWidth;
snowFlake.style.transitionProperty = 'transform';
snowFlake.style.transitionDuration = '1500ms';
snowFlake.style.transform = 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)';

يكمن المفتاح في تعليق "انتظار إطار". لبدء النقل بنجاح، يجب أن يقر المتصفح بأن العنصر في موضع البداية. هناك عدة طرق للقيام بذلك. إحدى الطرق الأكثر شيوعًا هي القراءة من إحدى خصائص العناصر التي تفرض على المتصفّح احتساب التنسيق، ما يضمن معرفة أنّ العنصر له موضع بداية قبل الانتقال إلى موضع النهاية. يتيح لك استخدام هذه الطريقة تهنئة نفسك على معرفتك الفائقة بالعناصر الداخلية للمتصفح مع الحفاظ على شعورك بعدم الوضوح مع كل ضغطة مفتاح.

في المقابل، لم يكن من الممكن أن تكون استدعاء element.animate() المكافئة أكثر وضوحًا، مع توضيح ما هو المقصود بالضبط:

snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);

يوجد العديد من الخيارات الأخرى. تمامًا كما هو الحال مع نظيراتها في CSS، قد تتأخر Web Animations وتكرارها:

snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], {
    duration: 1500,
    iterations: 10,
    delay: 300
});

AnimationPlayer

يعرض element.animate() في الواقع كائن AnimationPlayer، وهو ما سيصبح مهمًا بشكل متزايد مع إطلاق المزيد من مواصفات Web Animations. تحتوي الرسوم المتحركة التي يتم إنشاؤها باستخدام كل من JavaScript وCSS على AnimationPlayers، ما يتيح إمكانية دمجها بسلاسة بطرق مفيدة ومثيرة للاهتمام.

مع ذلك، لا يحتوي AnimationPlayer حاليًا سوى على جزأين من الوظائف، وكلاهما مفيد جدًا. يمكنك إلغاء صورة متحركة في أي وقت باستخدام AnimationPlayer.cancel():

var player = snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
// less than 1500ms later...changed my mind
player.cancel();

ولمساعدة كل من حاول إنشاء نظام صور متحركة يتمحور حول CSS Animations أو عمليات النقل في السابق، تنشِّط Web Animations دائمًا حدثًا عند انتهائها:

var player = snowFlake.animate([
    {transform: 'translate(' + snowLeft + 'px, -100%)'},
    {transform: 'translate(' + snowLeft + 'px, ' + window.innerHeight + 'px)'}
], 1500);
player.onfinish = function(e) {
    console.log('per aspera ad terra!');
}

تجربة السمات والبيانات

سيتم نقل هذه الدفعة بالكامل إلى الإصدار 36 من Chrome، وسيتم نقلها إلى الإصدار التجريبي اليوم. إذا كنت تريد تجربتها، فجرب العمل باستخدام التنفيذ الأصلي في Chrome 36. ومع ذلك، هناك رمز polyfill لـ Web Animations، والذي يوفّر جزءًا أكبر بكثير من مواصفات Web Animations الكاملة لأي من المتصفحات الحديثة الدائمة.

يتوفّر لك عرض توضيحي لتأثير الثلج لتجربة استخدام كل من الإصدار الأصلي من element.animate() وpolyfill.

يسرنا أن نعرف رأيك

مع ذلك، توفّر هذه اللعبة معاينة لما سيأتي لاحقًا، وسيتم إصدارها خصيصًا للحصول على ملاحظات المطوّرين وآرائهم على الفور. لسنا متأكدين حتى الآن مما إذا كنا قد وصلنا إلى كل حالة استخدام أو صقلنا جميع الحدود التقريبية لواجهات برمجة التطبيقات الحالية للصور المتحركة. الطريقة الوحيدة لمعرفة ذلك وتصحيحه هو أن يجرِّب المطوّرون هذا البرنامج وإعلامنا بآرائهم.

لا شك في أنّ التعليقات على هذه المشاركة قيّمة، ويمكن توجيه التعليقات على المعيار نفسه إلى مجموعات عمل CSS وSVG عبر القائمة البريدية العامة.

تحديث، تشرين الأول (أكتوبر) 2014: يضيف Chrome 39 الدعم لعدة طرق إضافية تتعلق بالتحكم في التشغيل، مثل play() وpause() وreverse(). وتتيح أيضًا الانتقال إلى نقطة معيّنة في المخطط الزمني للصورة المتحركة باستخدام السمة currentTime. يمكنك الاطّلاع على هذه الوظيفة أثناء استخدامها في هذا العرض التوضيحي الجديد.

نشكر "أدي عثمان" و"ماكس هاينريتز" على مساعدتهما في هذه المشاركة.