دليل تفصيلي حول تطوير التطبيقات المتوافقة مع أجهزة متعددة
في مقالتنا الأولى حول تطوير تجربة Chrome A Journey Through Middle-earth، ركّزنا على تطوير WebGL للأجهزة الجوّالة. في هذه المقالة، نناقش التحديات والمشاكل والحلول التي واجهناها عند إنشاء بقية الواجهة الأمامية لتطبيق HTML5.
ثلاثة إصدارات من الموقع الإلكتروني نفسه
لنبدأ بالحديث قليلاً عن تكييف هذه التجربة للعمل على كلّ من أجهزة الكمبيوتر المكتبي والأجهزة الجوّالة من منظور حجم الشاشة وإمكانات الجهاز.
يستند المشروع بأكمله إلى أسلوب "سينمائي" للغاية، حيث أردنا من الناحية التصميمية الحفاظ على التجربة ضمن إطار ثابت بالوضع الأفقي للحفاظ على سحر الفيلم. وبما أنّ جزءًا كبيرًا من المشروع يتألف من "ألعاب" صغيرة تفاعلية، لن يكون من المنطقي السماح لها بالخروج عن الإطار أيضًا.
يمكننا أن نأخذ الصفحة المقصودة كمثال على كيفية تكييف التصميم لأحجام مختلفة.
يتضمّن الموقع الإلكتروني ثلاثة أوضاع مختلفة: الكمبيوتر المكتبي والجهاز اللوحي والجهاز الجوّال. ليس فقط لمعالجة التنسيق، ولكن لأنّنا نحتاج إلى معالجة مواد العرض المحمَّلة أثناء التشغيل وإضافة تحسينات مختلفة للأداء. مع الأجهزة التي تتمتع بدرجة دقة أعلى من أجهزة الكمبيوتر المكتبي والمحمول ولكنّها تحقّق أداءً أسوأ من الهواتف، ليس من السهل تحديد المجموعة النهائية من القواعد.
نستخدم بيانات وكيل المستخدم لرصد الأجهزة الجوّالة واختبار حجم مساحة العرض لاستهداف الأجهزة اللوحية من بين تلك الأجهزة (645 بكسل أو أكثر). يمكن لكل وضع مختلف عرض جميع درجات الدقة، لأنّ التنسيق يستند إلى طلبات البحث عن الوسائط أو موضع النسبة المئوية/النسبة النسبية باستخدام JavaScript.
بما أنّ التصميمات في هذه الحالة لا تستند إلى شبكات أو قواعد، وهي فريدة جدًا بين الأقسام المختلفة، يعتمد الأمر حقًا على العنصر والسيناريو المحدّدَين بشأن نقاط التوقف أو الأنماط التي يجب استخدامها. حدث ذلك أكثر من مرة أنّنا أعددنا التنسيق المثالي باستخدام مجموعات sass-mixins وطلبات البحث عن الوسائط الجميلة، ثم احتجنا إلى إضافة تأثير استنادًا إلى موضع الماوس أو الأجسام الديناميكية، وانتهى بنا الأمر بإعادة كتابة كل شيء في JavaScript.
نضيف أيضًا فئة تتضمّن الوضع الحالي في علامة العنوان لنتمكّن من استخدام هذه المعلومات في أنماطنا، كما هو موضّح في هذا المثال (باستخدام SCSS):
.loc-hobbit-logo {
// Default values here.
.desktop & {
// Applies only in desktop mode.
}
.tablet &, .mobile & {
// Different asset for mobile and tablets perhaps.
@media screen and (max-height: 760px), (max-width: 760px) {
// Breakpoint-specific styles.
}
@media screen and (max-height: 570px), (max-width: 400px) {
// Breakpoint-specific styles.
}
}
}
نوفّر جميع الأحجام حتى 360×320 تقريبًا، ما كان يشكّل تحديًا كبيرًا عند إنشاء تجربة غامرة على الويب. على أجهزة الكمبيوتر المكتبي، نضع حدًا أدنى للحجم قبل عرض أشرطة التمرير لأنّنا نريد أن تشاهد الموقع الإلكتروني في مساحة عرض أكبر إن أمكن. على الأجهزة الجوّالة، قرّرنا السماح بالوضع الأفقي والعمودي في جميع التجارب، باستثناء التجارب التفاعلية التي نطلب منك فيها قلب الجهاز إلى الوضع الأفقي. كان الاعتراض على ذلك هو أنّه ليس غامرًا في الوضع العمودي كما هو الحال في الوضع الأفقي، ولكن تم توسيع نطاق الموقع الإلكتروني بشكل جيد، لذلك احتفظنا به.
من المهمّ ملاحظة أنّه يجب عدم الخلط بين التنسيق وميزة رصد الميزات، مثل نوع الإدخال واتجاه الجهاز وأجهزة الاستشعار وما إلى ذلك. يمكن أن تتوفّر هذه الميزات في جميع هذه الأوضاع ويجب أن تسري على جميعها. ومن الأمثلة على ذلك إتاحة استخدام الماوس واللمس في الوقت نفسه. تعويض الشاشة المحسّنة للجودة، ولكن الأهم من ذلك هو الأداء، وفي بعض الأحيان تكون الجودة الأقل أفضل. على سبيل المثال، تكون اللوحة نصف درجة الدقة في تجارب WebGL على شاشات Retina، والتي كان يجب أن تُعرِض أربعة أضعاف عدد وحدات البكسل.
لقد استخدمنا أداة المحاكي في "أدوات مطوّري البرامج" بشكلٍ متكرّر أثناء التطوير، خاصةً في Chrome Canary الذي يتضمّن ميزات جديدة محسّنة والعديد من الإعدادات المُسبَقة. وهي طريقة جيدة للتحقّق من التصميم بسرعة. ما زلنا بحاجة إلى إجراء الاختبار على الأجهزة الحقيقية بانتظام. أحد الأسباب هو أنّ الموقع الإلكتروني يتكيّف مع الشاشة الكاملة. تخفي الصفحات التي تتضمّن ميزة الانتقال العمودي للمحتوى واجهة مستخدم المتصفّح عند الانتقال للأسفل أو للأعلى في معظم الحالات (يواجه Safari على نظام التشغيل iOS 7 مشاكل في هذا الشأن حاليًا)، ولكن كان علينا ملاءمة كل المحتوى بغض النظر عن ذلك. استخدمنا أيضًا إعدادًا مُعدّ مسبقًا في المحاكي وغيّرنا إعداد حجم الشاشة لمحاكاة فقدان المساحة المتوفّرة. من المهم أيضًا إجراء الاختبار على الأجهزة الحقيقية لمراقبة استهلاك الذاكرة والأداء.
التعامل مع الحالة
بعد الصفحة المقصودة، ننتقل إلى خريطة الأرض الوسطى. هل لاحظت تغيير عنوان URL؟ الموقع الإلكتروني هو تطبيق صفحة واحدة يستخدم History API لمعالجة التوجيه.
كل قسم من الموقع الإلكتروني هو عنصر يرث مجموعة من الوظائف، مثل عناصر DOM والانتقالات وتحميل مواد العرض والتخلص منها وما إلى ذلك. عند استكشاف أجزاء مختلفة من الموقع الإلكتروني، يتم بدء الأقسام وإضافة عناصر إليها وإزالتها من DOM وتحميل مواد عرض القسم الحالي.
بما أنّه يمكن للمستخدم النقر على زر الرجوع في المتصفّح أو الانتقال عبر القائمة في أي وقت، يجب التخلص من كل ما تم إنشاؤه في مرحلة ما. يجب إيقاف مهلات الانتظار والصور المتحركة ورفضها، وإلا ستؤدي إلى ظهور سلوك غير مرغوب فيه وأخطاء وتسرُّب للذاكرة. هذه المهمة ليست سهلة دائمًا، خاصةً عندما تقترب المواعيد النهائية ويكون عليك إدراج كل المحتوى في أسرع وقت ممكن.
عرض المواقع الجغرافية
لإبراز المناظر الجميلة وشخصيات "أرض الوسط"، أنشأنا نظامًا وحدات من مكوّنات الصور والنصوص التي يمكنك سحبها أو التمرير عليها أفقيًا. لم نتيح شريط التمرير هنا لأنّنا نريد استخدام سرعات مختلفة في نطاقات مختلفة، مثل تسلسلات الصور التي تتوقف فيها الحركة الجانبية إلى أن يتم تشغيل المقطع.
المخطط الزمني
عندما بدأنا عملية التطوير، لم نكن نعرف محتوى الوحدات لكل موقع جغرافي. لقد أردنا طريقة مستندة إلى نموذج لعرض أنواع مختلفة من الوسائط والمعلومات في مخطط زمني أفقي يمنحنا الحرية في إنشاء ستة عروض مختلفة للمواقع الجغرافية بدون الحاجة إلى إعادة إنشاء كل شيء ست مرات. لإدارة ذلك، أنشأنا وحدة تحكّم في المخطط الزمني تتولى إدارة التمرير في وحداتها استنادًا إلى الإعدادات وسلوكيات الوحدات.
الوحدات ومكونات السلوك
تتضمّن الوحدات المختلفة التي أضفنا دعمًا لها تسلسل الصور والصور الثابتة ومشهد التماثل البصري ومشهد تغيير التركيز والنص.
تحتوي وحدة المشهد المتغير الإيحاء بحركة العناصر على خلفية غير شفافة بعدد مخصّص من الطبقات التي تستمع إلى مستوى تقدّم إطار العرض للاطّلاع على المواضع الدقيقة.
مشهد تغيير التركيز هو نوع من أنواع حزمة المجسمات الثلاثية الأبعاد، مع إضافة أنّنا نستخدم صورتَين لكل طبقة تتلاشى وتظهر لمحاكاة تغيير التركيز. لقد حاولنا استخدام فلتر التمويه، ولكنّه لا يزال باهظًا، لذا سننتظر أدوات تظليل CSS لتنفيذ ذلك.
يمكن سحب المحتوى في وحدة النص باستخدام المكوّن الإضافي TweenMax Draggable. يمكنك أيضًا استخدام عجلة التمرير أو التمرير سريعًا باستخدام إصبعين للانتقال عموديًا. يُرجى ملاحظة throw-props-plugin الذي يضيف التأثيرات الفيزيائية على غرار رمي الأشياء عند التمرير سريعًا والإفلات.
يمكن أن تتضمّن الوحدات أيضًا سلوكيات مختلفة تتم إضافتها كمجموعة من المكونات. ولكلّ منها أدوات اختيار الاستهداف وإعداداته الخاصة. يمكنك الترجمة لنقل عنصر، وتغيير الحجم للتكبير/التصغير، وتحديد نقاط ساخنة لتطبيق تراكب المعلومات، ومقاييس تصحيح الأخطاء للاختبار المرئي، وتطبيق تراكب عنوان البداية، وطبقة وميض، وغير ذلك. وسيتم إلحاقها بنموذج DOM أو التحكّم في العنصر المستهدَف داخل الوحدة.
بعد تنفيذ ذلك، يمكننا إنشاء المواقع الجغرافية المختلفة باستخدام ملفّ إعداد يحدّد ملفّات الأصول التي يجب تحميلها وإعداد الأنواع المختلفة من الوحدات والمكوّنات.
تسلسلات الصور
إنّ تسلسل الصور هو أكثر الوحدات صعوبة من حيث الأداء وحجم التنزيل. هناك الكثير من المعلومات حول هذا الموضوع. أما على الأجهزة الجوّالة والأجهزة اللوحية، فنستبدلها بصورة ثابتة. هذه بيانات كثيرة جدًا لفك ترميزها وتخزينها في الذاكرة إذا أردنا تحقيق جودة جيدة على الأجهزة الجوّالة. لقد جرّبنا عدة حلول بديلة، مثل استخدام صورة خلفية وجدول صور متحركة أولاً، ولكنّ ذلك أدّى إلى مشاكل في الذاكرة وتأخّر في الأداء عندما تحتاج وحدة معالجة الرسومات إلى التبديل بين جداول الصور المتحركة. بعد ذلك، حاولنا تبديل عناصر img، ولكنّ ذلك كان بطيئًا جدًا أيضًا. كان رسم إطار من لوحة صور متحركة إلى لوحة صورة يحقّق أفضل أداء، لذا بدأنا في تحسينه. لتوفير وقت الحساب في كل إطار، تتم معالجة بيانات الصورة المطلوب كتابتها في اللوحة مسبقًا من خلال لوحة مؤقتة ويتم حفظها باستخدام putImageData() في صفيف، ويتم فك ترميزها وتكون جاهزة للاستخدام. يمكن بعد ذلك جمع المهملات من لوحة رموز المتحركة الأصلية، ولا نخزِّن في الذاكرة سوى الحد الأدنى من البيانات المطلوبة. قد يكون من الأسهل تخزين الصور غير المُشفَّرة، ولكن نحصل على أداء أفضل أثناء تمرير التسلسل بهذه الطريقة. تكون اللقطات صغيرة جدًا، بدقة 640×400 فقط، ولكن لن تظهر إلا أثناء التمرير السريع. عند التوقف، يتم تحميل صورة عالية الدقة وتظهر تدريجيًا بسرعة.
var canvas = document.createElement('canvas');
canvas.width = imageWidth;
canvas.height = imageHeight;
var ctx = canvas.getContext('2d');
ctx.drawImage(sheet, 0, 0);
var tilesX = imageWidth / tileWidth;
var tilesY = imageHeight / tileHeight;
var canvasPaste = canvas.cloneNode(false);
canvasPaste.width = tileWidth;
canvasPaste.height = tileHeight;
var i, j, canvasPasteTemp, imgData,
var currentIndex = 0;
var startIndex = index * 16;
for (i = 0; i < tilesY; i++) {
for (j = 0; j < tilesX; j++) {
// Store the image data of each tile in the array.
canvasPasteTemp = canvasPaste.cloneNode(false);
imgData = ctx.getImageData(j * tileWidth, i * tileHeight, tileWidth, tileHeight);
canvasPasteTemp.getContext('2d').putImageData(imgData, 0, 0);
list[ startIndex + currentIndex ] = imgData;
currentIndex++;
}
}
يتم إنشاء جداول الصور الرمزية باستخدام Imagemagick. في ما يلي مثال بسيط على GitHub يعرض كيفية إنشاء جدول صور متحركة لكل الصور داخل مجلد.
إضافة تأثيرات متحركة إلى الوحدات
لوضع الوحدات على المخطط الزمني، يتم تتبُّع "أداة التحكّم في التشغيل" وعرض المخطط الزمني بشكل مخفي خارج الشاشة. يمكن إجراء ذلك باستخدام الرمز البرمجي فقط، ولكن كان من الجيد استخدام تمثيل مرئي عند التطوير وتصحيح الأخطاء. عند التشغيل الفعلي، يتم تعديله فقط عند إعادة الحجم لضبط الأبعاد. تملأ بعض الوحدات مساحة العرض، بينما تتّبع بعض الوحدات نسبة عرض إلى ارتفاع خاصة بها، لذا كان من الصعب بعض الشيء تغيير حجم كل العناصر ووضعها في جميع درجات الدقة حتى تظهر كل العناصر ولا يتم اقتصاصها كثيرًا. تحتوي كل وحدة على مؤشّرَين للتقدّم، أحدهما للموضع الظاهر على الشاشة والآخر لمدة الوحدة نفسها. عند إنشاء تأثير التماثل البصري، غالبًا ما يكون من الصعب احتساب موضع البداية والنهاية للعناصر لمزامنته مع الموضع المتوقّع عند ظهورها. من المهم معرفة الوقت الدقيق الذي تدخل فيه الوحدة إلى العرض، ووقت تشغيل المخطط الزمني الداخلي لها، ووقت اختفائها من العرض مرة أخرى.
تحتوي كل وحدة على طبقة سوداء خفيفة في الأعلى تعمل على ضبط مستوى التعتيم لتصبح شفافة تمامًا عندما تكون في الموضع المركزي. يساعدك ذلك في التركيز على وحدة واحدة في كل مرة، ما يعزّز التجربة.
أداء الصفحة
إنّ الانتقال من نموذج أولي يعمل إلى إصدار خالٍ من الانقطاعات يعني الانتقال من التخمين إلى معرفة ما يحدث في المتصفّح. في هذه الحالة، تكون "أدوات مطوّري البرامج في Chrome" هي أفضل صديق لك.
لقد قضينا وقتًا طويلاً في تحسين الموقع الإلكتروني. إنّ فرض ميزة "تسريع الأجهزة" هي إحدى أهم الأدوات بالطبع للحصول على صور متحركة سلسة. ولكن عليك أيضًا البحث عن الأعمدة الملونة والمستطيلات الحمراء في "أدوات مطوّري البرامج في Chrome". هناك العديد من المقالات الجيدة حول المواضيع، ويجب قراءتها كلها. إنّ مكافأة إزالة اللقطات التي يتم تخطّيها فورية، ولكنّ الإحباط الذي يصيبك عند عودتها مرة أخرى يكون فوريًا أيضًا. وسنفعل ذلك. وهي عملية مستمرة تحتاج إلى تكرار.
أفضّل استخدام TweenMax من Greensock لعملية التقديم والترجيع للسمات والتحويلات وCSS. فكِّر في الحاويات، وتصوَّر البنية أثناء إضافة طبقات جديدة. تجدر الإشارة إلى أنّ عمليات التحويل الجديدة يمكن أن تستبدل عمليات التحويل الحالية. يتم استبدال دالة translateZ(0) التي تفرض تسريع الأجهزة في فئة CSS الخاصة بك بمصفوفة ثنائية الأبعاد إذا كنت تستخدم القيم الثنائية الأبعاد فقط. لإبقاء الطبقة في وضع التسارع في هذه الحالات، استخدِم السمة force3D:true في الفاصل الزمني لإنشاء مصفوفة ثلاثية الأبعاد بدلاً من مصفوفة ثنائية الأبعاد. من السهل نسيان ذلك عند دمج عمليات النقل السلس في CSS وJavaScript لضبط الأنماط.
لا تفرض ميزة "تسريع الأجهزة" في حال عدم الحاجة إليها. يمكن أن تمتلئ ذاكرة وحدة معالجة الرسومات بسرعة وتؤدي إلى نتائج غير مرغوب فيها عندما تريد تسريع العديد من الحاويات باستخدام الأجهزة، خاصةً على نظام التشغيل iOS حيث تكون الذاكرة أكثر تقييدًا. تم إجراء تحسينات كبيرة من خلال تحميل مواد عرض أصغر حجمًا وتوسيع نطاقها باستخدام css وإيقاف بعض التأثيرات في وضع الأجهزة الجوّالة.
كان تسرُّب الذاكرة مجالًا آخر احتاجنا إلى تحسين مهاراتنا فيه. عند الانتقال بين تجارب WebGL المختلفة، يتم إنشاء الكثير من الكائنات والمواد والقوام والأشكال الهندسية. إذا لم تكن هذه العناصر جاهزة لجمع المهملات عند الانتقال بعيدًا عن القسم وإزالته، من المحتمل أن يؤدي ذلك إلى تعطُّل الجهاز بعد فترة عندما تنفد ذاكرته.
للعثور على تسرُّب الذاكرة، كان سير العمل في أدوات مطوري البرامج مباشرًا جدًا، حيث تم تسجيل المخطط الزمني والتقاط لقطات ذاكرة عشوائية. من الأسهل فلترة عناصر معيّنة، مثل الأشكال الهندسية الثلاثية الأبعاد أو مكتبة معيّنة. في المثال أعلاه، تبيّن أنّ المشهد الثلاثي الأبعاد لا يزال متوفّرًا، ولم يتم أيضًا محو صفيف يخزّن الأشكال الهندسية. إذا كان من الصعب عليك تحديد مكان العنصر، تتوفّر ميزة رائعة تتيح لك الاطّلاع عليه تُسمى الاحتفاظ بالمسارات. ما عليك سوى النقر على العنصر الذي تريد فحصه في لقطة الذاكرة المؤقتة وستظهر لك المعلومات في لوحة أسفل الصفحة. يساعد استخدام بنية جيدة مع عناصر أصغر حجمًا في تحديد موقع المراجع.
بشكل عام، من الأفضل التفكير جيدًا قبل التلاعب بـ DOM. عند إجراء ذلك، ننصحك بالتفكير في الكفاءة. تجنَّب التلاعب بـ DOM داخل حلقة ألعاب إذا أمكن. تخزين الإشارات في المتغيّرات لإعادة استخدامها إذا كنت بحاجة إلى البحث عن عنصر، استخدِم أقصر طريق من خلال تخزين إحالات إلى الحاويات الاستراتيجية والبحث داخل أقرب عنصر أصلي.
يمكنك تأخير قراءة سمات العناصر التي تمت إضافتها حديثًا أو عند إزالة/إضافة فئات إذا واجهت أخطاء في التنسيق. أو تأكَّد من تفعيل التنسيق. في بعض الأحيان، يُجري المتصفّح تغييرات مجمّعة على الأنماط، ولن يتم تعديلها بعد بدء التنسيق التالي. يمكن أن يشكّل ذلك مشكلة كبيرة في بعض الأحيان، ولكن هناك سبب لذلك، لذا ننصحك بالتعرّف على آلية عمل هذه الميزة وستستفيد كثيرًا من ذلك.
ملء الشاشة
يمكنك وضع الموقع الإلكتروني في وضع ملء الشاشة في القائمة من خلال Fullscreen API عندما يكون هذا الخيار متاحًا. ولكن على الأجهزة، يعتمد ذلك أيضًا على قرار المتصفّح بعرض الفيديو في وضع ملء الشاشة. كان متصفّح Safari على أجهزة iOS يتضمّن سابقًا خدعة تتيح لك التحكّم في ذلك، ولكنّ هذه الخدعة لم تعُد متاحة، لذا عليك إعداد تصميمك للعمل بدونها عند إنشاء صفحة لا يمكن التمرير فيها. من المحتمل أن نتوقع تحديثات بشأن هذا في التحديثات المستقبلية، لأنّه أدّى إلى تعطُّل الكثير من تطبيقات الويب.
مواد العرض
لدينا الكثير من أنواع مواد العرض المختلفة على الموقع الإلكتروني، فنحن نستخدم الصور (بتنسيق PNG وJPEG) ورسومات SVG (المضمّنة والخلفية) وأوراق الرموز (بتنسيق PNG) وخطوط الرموز المخصّصة وصور Adobe Edge المتحركة. نستخدم ملفات PNG لمواد العرض والصور المتحركة (جداول الصور المتحركة) التي لا يمكن أن يكون عنصرها مستندًا إلى الرسومات المتجهّة، وإلا نحاول استخدام ملفات SVG قدر الإمكان.
لا يؤدي تنسيق المتجه إلى فقدان الجودة، حتى إذا غيّرنا حجمه. ملف واحد لجميع الأجهزة
- حجم ملف صغير
- يمكننا إضافة تأثيرات متحركة إلى كل جزء على حدة (وهو مثالي للتأثيرات المتحركة المتقدّمة). على سبيل المثال، نخفي "العنوان الفرعي" لشعار Hobbit (مشهد خراب Smaug) عند تصغير حجمه.
- ويمكن تضمينها كعلامة HTML لرسومات SVG أو استخدامها كصورة خلفية بدون تحميل إضافي (يتم تحميلها في الوقت نفسه الذي يتم فيه تحميل صفحة html).
تتمتع خطوط أحرف الرموز بالميزات نفسها التي تتمتع بها ملفات SVG في ما يتعلق بقابلية التوسيع، ويتم استخدامها بدلاً من ملفات SVG للعناصر الصغيرة مثل الرموز التي نحتاج فقط إلى تغيير لونها (عند التمرير فوقها أو عند تفعيلها أو غير ذلك). من السهل أيضًا إعادة استخدام الرموز، ما عليك سوى ضبط سمة CSS "المحتوى" لأحد العناصر.
الصور المتحركة
في بعض الحالات، قد يستغرق إنشاء صور SVG متحركة باستخدام الرموز البرمجية وقتًا طويلاً، خاصةً عندما يكون من الضروري تغيير الصورة المتحركة كثيرًا أثناء عملية التصميم. لتحسين سير العمل بين المصمّمين والمطوّرين، نستخدم Adobe Edge لبعض الرسوم المتحرّكة (التعليمات قبل الألعاب). تشبه سير عمل الرسوم المتحركة Flash كثيرًا، ما ساعد الفريق، ولكن هناك بعض العيوب، لا سيما عند دمج الرسوم المتحركة في Edge في عملية تحميل مواد العرض لأنّها تأتي مع أدوات تحميل ومنطق تنفيذ خاص بها.
ما زلنا نعتقد أنّنا بحاجة إلى مزيد من الوقت قبل أن نحصل على سير عمل مثالي لمعالجة مواد العرض والرسوم المتحرّكة المصنوعة يدويًا على الويب. نحن نتطلّع إلى رؤية كيفية تطوير أدوات مثل Edge. يُرجى إضافة اقتراحات حول أدوات الرسوم المتحركة ومسارات العمل الأخرى في قسم التعليقات.
الخاتمة
الآن بعد أن تم إصدار جميع أجزاء المشروع ونظرنا إلى النتيجة النهائية، يجب أن أقول إنّنا معجبون جدًا بحالة متصفّحات الأجهزة الجوّالة الحديثة. عندما بدأنا هذا المشروع، لم تكن لدينا توقعات كبيرة بشأن مدى سلاسة الدمج والأداء الذي يمكننا تحقيقه. لقد كانت تجربة تعلّم رائعة بالنسبة إلينا، وقد أدّى كل الوقت الذي قضيناناه في إجراء عمليات التكرار والاختبار (الكثير) إلى تحسين فهمنا لطريقة عمل المتصفّحات الحديثة. وهذا هو ما سنحتاج إليه إذا أردنا تقليل وقت الإنتاج لهذه الأنواع من المشاريع، من التخمين إلى المعرفة.