لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 05/16/25 في كل الموقع
-
5 نقاط
-
4 نقاط
-
4 نقاط
-
السلام عليكم ورحمة الله وبركاته عندي استفسار بخصوص استخدام نماذج الانحدار مع البيانات الزمنية: عندما يكون لدي بيانات زمنية (مثل المبيعات أو الإنتاج اليومي)، وأقوم بتطبيق نماذج Linear Regression أو Polynomial Regression بهدف توقع القيم المستقبلية، ألاحظ أن هذا يعتبر Extrapolation (توقع خارج نطاق البيانات المتاحة). هل يعتبر هذا الأسلوب صحيح علميًا لتوقع القيم المستقبلية في البيانات الزمنية؟ وإذا لم يكن صحيحا فما فائدة هذه النماذج إذا ؟ وهل من الأفضل الاعتماد على نماذج مخصصة للبيانات الزمنية مثل AutoTS أو ARIMA بدلاً من استخدام نماذج الانحدار العادية؟ مع العلم أنها تستخدم أيضا نماذج الانحدار ؟ وما الفرق الجوهري بين استخدام Regression العادي وTime Series Models فيما يخص توقع البيانات المستقبلية؟2 نقاط
-
2 نقاط
-
2 نقاط
-
مرحبا.....بعد ان قمت بتحميل الوامب على حهازي....احاول تشغيل الوامب فيظهر بلون اخضر ولكن لا تظهر القائمة الخاصة به عند النقر عليه......دخلت الى متصفح chrome وكتبت localhost/.....وهنا المشكلة فالصفحة لا تعمل ويظهر لي صفحة بلون برتقالي على شكل جدولين وهذه الكتابة فيهما : ( ! ) Warning: require(../files/apacheloadedmodules.php): Failed to open stream: No such file or directory in C:\wamp64\www\index.php on line 230 Call Stack #TimeMemoryFunctionLocation 10.1027487392{main}( )...\index.php:0 ( ! ) Fatal error: Uncaught Error: Failed opening required '../files/apacheloadedmodules.php' (include_path='.;C:\php\pear') in C:\wamp64\www\index.php on line 230 ( ! ) Error: Failed opening required '../files/apacheloadedmodules.php' (include_path='.;C:\php\pear') in C:\wamp64\www\index.php on line 230 Call Stack #TimeMemoryFunctionLocation 10.1027487392{main}( )...\index.php:0 ارجو المساعدة في اقرب وقت وشكرا جزيلا1 نقطة
-
Linear أو Polynomial Regression مع الوقت كمتغير وحيد ليس خطأ بالمعنى الرياضي، لكنه ضعيف علميًا كأداة تنبؤ في السلاسل الزمنية لأنك تفترض ضمنيًا أنّ ما كان يحدث سيستمر بلا تغيير. فنماذج السلاسل الزمنية ARIMA, ETS, Prophet, AutoTS وغيرهم مبنية خصيصًا للتعامل مع الخصائص التي تُميز البيانات الزمنية، أي الاعتماد الذاتي Autocorrelation، الموسمية Seasonality، عدم الثبات Non-stationarity، والصدمات البنيوية Structural breaks. بالتالي بإمكانك إعتبار ARIMA وغيره على أنه انحدار أيضًا ولكن على متغيرات مشتقة وهي الفروق، القيم المتأخرة وخلافه، وبآلية تحقق من صلاحية الفرضيات الإحصائية stationarity, white noise إلخ.1 نقطة
-
المشكلة هي في navbar لا يتم تنسيقها برغم ان لا يوجد اي مشكلة في الاكواد لقد غيرت لون خلفية body وتم تنفيذ لكن قسم links ولي هو home, skills والى ما يلي اضفت لهم تنسيقات ولم تتنفذ1 نقطة
-
1 نقطة
-
نفس المشكلة هل هناك شئ أخر يمكن أن يكون سبب المشكلة؟ ليس لدي ملف php فقط أنا أريد بناء تطبيق ويب باستخدام ووردبريس1 نقطة
-
في هذا التمرين يتم طلب بناء نموذج للتنبؤ بحجم حركة المرور بناء على عدد الركاب في قطار أو مترو وذلك باستخدام البيانات المقدمة في ملف يسمى Metro_Interstate_Traffic_Volume. أولا البيانات (Dataset): إن اسم مجموعة البيانات هو Metro_Interstate_Traffic_Volume وتحتوي تلك البيانات على معلومات تتعلق بحركة القطارات و المترو في الولايات المتحدة الأمريكية USA . ثانيا الميزات (Features) وهذه هي المتغيرات (الأعمدة) الموجودة في مجموعة البيانات والتي ستستخدمها للتنبؤ: درجة الحرارة (Temperature). المطر (Rain). العطلات (Holidays). التاريخ والوقت (Date and Time). حجم المرور (Traffic Volume). ثالثا الهدف (Objective) : حيث الهدف الرئيسي هنا هو التنبؤ بقيمة حجم حركة المرور ولتتخيل أنه تطبيق عملي يمكن أن يساعد المستخدمين على معرفة ما إذا كانت محطات القطار ستكون مزدحمة بناء على حجم حركة المرور المتوقعة. ورابعا التعليمات لك في التمرين (Instructions) : الهدف لك هو تحقيق دقة أعلى من زملائك. ويجب عليك استخدام نهجين مختلفين للتنبؤ: تقنية كلاسيكية (Classical Technique): مثل الانحدار الخطي (Linear Regression) أو الغابات العشوائية (Random Forest) أو غيرها من خوارزميات التعلم الآلي التقليدية. شبكة عصبية (Neural Network). ومسموح لك بإجراء أي معالجة مسبقة للبيانات (Data Preprocessing) تراها ضرورية لتحسين أداء النموذج . وتلخيصا لما سبق المطلوب منك هو بناء نموذج يتنبأ بعدد الركاب (Traffic Volume) بناء على عوامل مثل درجة الحرارة و المطر و العطلات والوقت. ويجب عليك تجربة نوعين من النماذج (كلاسيكي والشبكة العصبية) ومقارنة نتائجهما لتقديم النتائج الأفضل. ويمكنك تعديل وتنظيف البيانات حسب الحاجة لتحسين الأداء.1 نقطة
-
ذلك تمرين حول التنبؤ بحجم حركة مرور القطارات بالإعتماد على بيانات معينة، المطلوب منك هو بناء نموذج يتنبأ بحجم حركة مرور القطارات وذلك هو الـ Traffic Volume، الفائدة تظهر في حال أنك مثلاً تبني تطبيقًا يخبر المستخدمين هل محطة القطار ستكون مزدحمة أم لا؟ ستحتاج إلى البحث عن مجموعة بيانات تحتوي على معلومات درجة الحرارة، المطر، الأعياد، التاريخ والوقت، وحجم حركة المرور. وعليك استخدام طريقتين للتنبؤ، الأولى الطريقة التقليدية أو الكلاسيكية بواسطة الانحدار الخطي Linear Regression أو الغابات العشوائية Random Forest أو غيرهم. الثانية من خلال شبكة عصبية Neural Network لبناء نموذج يعتمد على الشبكات العصبية. وعليك محاولة تحقيق دقة أعلى من زملائك في التنبؤ، وأيضًأ معالجة البيانات إذا لزم الأمر، والملف يحتوي على تلميحات لمساعدتك في تلك الخطوة. ثم توفير تقرير عن أفضل النتائج التي حققتها باستخدام الطريقة التقليدية والشبكة العصبية. والخطوات الموجودة في الملف توجهك للخطوات كالتالي: تحميل البيانات وعرضها. إضافة عمود جديد يوضح هل اليوم هو عطلة نهاية أسبوع أم لا. تصور البيانات لفهم الاتجاهات والعلاقات. تشفير وتوسيع نطاق البيانات encoding and scaling باستخدام Pipelines. البحث عن الارتباطات بين المتغيرات. تقسيم البيانات إلى مجموعات تدريب واختبار. بناء وتقييم النموذج الكلاسيكي باستخدام Mean Absolute Error كمقياس للأداء. بناء وتقييم نموذج الشبكة العصبية باستخدام Mean Absolute Error كمقياس للأداء.1 نقطة
-
أولاً ليس هناك قاعدة محددة يجب إتباعها ولكن هناك بعض النصائح التي يمكنك الإستفادة منها لتسعير الأعمال المطلوبة منك ولاحظ أنه مع الوقت واكتساب الخبرة و تحليل أسعار المنافسين في منطقتك الجغرافية وعلى المنصات التي تعمل من خلالها ستتعلم أكثر كيفية تقديم أسعار منافسة وتناسب مجهودك. وبالإضافة للنصائح السابقة حاول توضيح ما يميزك عن غيرك من المطورين من سرعة التنفيذ، جودة الكود والخبرة في هذا مجال اشرح للعميل قيمة عملك بدلاً من التركيز فقط على السعر وذلك في حالة كنت لا تريد التنافس على السعر . ونصيحة لا تقوم بالتسعير بناءاً على رأي العميل حيث أنه لا يمكن للعميل تقدير المجهود الذي تبذله فبالطبع تقوم بالتسعير الذي تجده مناسب لمجهودك ولكن في بداية الأمر ربما تقوم بتقليل ثمن الخدمة للحصول على العمل ولكن لاحقاً لا يصبح الأمر كذلك تماماً1 نقطة
-
يمكن لرسوم JavaScript التعامل مع حالات لا يمكن أن تتعامل معها CSS، مثل التحرك على مسار معقد مختلف عن منحنيات بيزيه Bezier curves باستخدام دالة توقيت، أو رسوميات متحركة على لوحة رسم. استخدام الدالة setInterval يمكن إنجاز الرسوم المتحركة في صورة سلسلة من الإطارات، والتي تكون عادةً تغيرات صغيرةً في خصائص HTML/CSS، فعلى سبيل المثال: يؤدي تغيير قيمة الخاصية style.left من 0px إلى 100px إلى تحريك العنصر، وإذا زدنا هذه القيمة ضمن الدالة setInterval، فسيؤدي تغير مقداره 2px مع تأخير ضئيل، لتكرار العملية بمقدار 50 مرةً في الثانية، مما يجعل الحركة سلسةً وناعمةً، ويُتَّبع هذا الأسلوب في السينما، فعرض 24 إطارًا في الثانية يجعل الصورة سلسةً. إليك الشيفرة المجردة pseudo-code للفكرة: let timer = setInterval(function() { if (animation complete) clearInterval(timer); else increase style.left by 2px }, 20); // تغير بمقدار 2 بكسل بتأخير 20 ميلي ثانية يعطي 50 إطار في الثانية وهذا مثال أكثر تعقيدًا: let start = Date.now(); // تذكر وقت البدء let timer = setInterval(function() { // كم مضى من الوقت منذ البداية let timePassed = Date.now() - start; if (timePassed >= 2000) { clearInterval(timer); // أنهي الحركة بعد ثانيتين return; } // ارسم إطار الحركة في اللحظة الحالية draw(timePassed); }, 20); // عندما يتغير الوقت بين 0 و2000 ميلي ثانية // تتغير قيمة الخاصية من 0 بكسل إلى 400 بكسل function draw(timePassed) { train.style.left = timePassed / 5 + 'px'; } إليك المثال النموذجي التالي: شيفرة الملف index.html: <!DOCTYPE HTML> <html> <head> <style> #train { position: relative; cursor: pointer; } </style> </head> <body> <img id="train" src="https://js.cx/clipart/train.gif"> <script> train.onclick = function() { let start = Date.now(); let timer = setInterval(function() { let timePassed = Date.now() - start; train.style.left = timePassed / 5 + 'px'; if (timePassed > 2000) clearInterval(timer); }, 20); } </script> </body> </html> وستكون النتيجة: See the Pen JS-p3-05-JavaScript-animations -ex1 by Hsoub (@Hsoub) on CodePen. استخدام الدالة requestAnimationFrame لنفترض تنفيذ عدة حركات انتقالية معًا. إذا شغّلنا هذه الرسوم منفصلةً فسيعيد المتصفح -وعلى الرغم من أنّ لكل حركة دالة (setInterval(..., 20 خاصةً- رسم الصور بمعدل أكبر بكثير من 20 ميلي ثانية، ويحدث هذا لوجود أوقات بداية مختلفة لكل حركة، وبالتالي سيختلف تكرار التغيّر الذي ضبطناه عند 20 ميلي ثانية بالنسبة لكل حركة، وهكذا سنكوِّن حالات تشغيل مستقلةً لكل حركة انتقالية تتكرر كل 20 ميلي ثانية، وبكلمات أخرى انظر الشيفرة التالية: setInterval(function() { animate1(); animate2(); animate3(); }, 20) والتي ستكون أخفّ من ناحية التنفيذ على المتصفح من الشيفرة: setInterval(animate1, 20); // حركة انتقالية مستقلة setInterval(animate2, 20); // في أماكن مختلفة من السكربت setInterval(animate3, 20); ينبغي تجميع عمليات الرسم المستقلة لتسهيل الأمر على المتصفح، ولتخفيف الحِمل على وحدة المعالجة إلى جانب إظهار حركة أكثر نعومةً. تذكر دائمًا أنه يجب ألا نشغل عملية الرسم كل 20 ميلي ثانية، لأنها قد تزيد حمولة وحدة المعالجة، أو لوجود أسباب لتقليل عملية إعادة الرسم، مثل الحالة التي تكون ضمن نافذة مخفية للمتصفح. ولتمييز ذلك في JavaScript سنستخدم ميزةً تُدعى توقيت الحركة Animation timing، والتي تزوّدنا بالدالة requestAnimationFrame التي تتعامل مع هذه الأمور وأكثر، وإليك صيغة استخدامها: let requestId = requestAnimationFrame(callback) تجدول الدالة requestAnimationFrame دالة الاستدعاء callback للعمل في أقرب وقت يريد فيه المتصفح تنفيذ الحركة، فإذا نفَّذنا أي تغييرات على العناصر ضمن الدالة callback، فستُجمّع مع غيرها من دوال الاستدعاء التي تجدولها الدالة requestAnimationFrame ومع رسوميات CSS، وهكذا سيعيد المتصفح الحسابات الهندسية، ثم يعيد الرسم مرةً واحدةً بدلًا من مرات متعددة. يمكن استخدام القيمة requestId التي تعيدها الدالة requestAnimationFrame في إلغاء الاستدعاء: // ألغ تنفيذ الاستدعاءات المجدولة cancelAnimationFrame(requestId); لدالة الاستدعاء callback وسيط واحد، وهو الوقت الذي انقضى منذ بداية تحميل الصفحة مقدرًا بالميكروثانية، والذي يمكن الحصول عليه باستدعاء التابع performance.now. يُنفَّذ الاستدعاء callback مبكرًا إلا في حالة التحميل الزائد للمعالج، أو عندما تقارب بطارية الحاسوب المحمول على النفاد أو لأسباب مشابهة، وتظهر الشيفرة التالية الوقت المستغرق خلال مرات التنفيذ العشرة الأولى للدالة requestAnimationFrame، وهو عادةً بين 10-20 ميلي ثانية: <script> let prev = performance.now(); let times = 0; requestAnimationFrame(function measure(time) { document.body.insertAdjacentHTML("beforeEnd", Math.floor(time - prev) + " "); prev = time; if (times++ < 10) requestAnimationFrame(measure); }) </script> See the Pen JS-p3-05-JavaScript-animations -ex2 by Hsoub (@Hsoub) on CodePen. الرسومات المتحركة المهيكلة Structured animation سننشئ الآن دالةً أكثر عموميةً مبنيةً على الدالة requestAnimationFrame: function animate({timing, draw, duration}) { let start = performance.now(); requestAnimationFrame(function animate(time) { // يتحرك الزمنين 0 و1 let timeFraction = (time - start) / duration; if (timeFraction > 1) timeFraction = 1; // حساب الحالة الراهنة للرسوم المتحركة let progress = timing(timeFraction) draw(progress); // تنفيذ الرسم if (timeFraction < 1) { requestAnimationFrame(animate); } }); } تقبل الدالة animate ثلاثة معاملات تصف الحركة، وهي: duration: الزمن الكلي لتنفيذ الحركة مقدرًا بالميلي ثانية. (timing(timeFraction: دالة توقيت تشابه الخاصية transition-timing-function في CSS، وتعطي نسبة الوقت الذي انقضى (0 عند البداية و1 عند النهاية)، وتعيد ما يدل على اكتمال الحركة، مثل الإحداثي y عند رسم منحني بيزيه، ولنتذكر أن الدالة الخطية تعني أن الحركة ستتقدم بانتظام وبالسرعة ذاتها: function linear(timeFraction) { return timeFraction; } وسيبدو الرسم البياني للدالة الخطية كالتالي: وهي مشابهة تمامًا للخاصية transition-timing-function، وسنرى لاحقًا بعض أشكال الاستخدام الأخرى. (draw(progress: وهي الدالة التي تأخذ معاملًا هو مقدار اكتمال الحركة وترسمه، وتشير القيمة progress=0 إلى حالة بداية الحركة، بينما تشير القيمة progress=1 إلى حالة النهاية، فهي الدالة التي ترسم الحركة فعليًا، إذا يمكنها نقل عنصر مثلًا: function draw(progress) { train.style.left = progress + 'px'; } أو تنفيذ أي شيء آخر، وبالتالي يمكننا تحريك أي شيء بالطريقة التي نريد، لنحرّك العنصر width من 0 حتى 100% باستخدام هذه الدالة: شيفرة الملف animate.js: unction animate({duration, draw, timing}) { let start = performance.now(); requestAnimationFrame(function animate(time) { let timeFraction = (time - start) / duration; if (timeFraction > 1) timeFraction = 1; let progress = timing(timeFraction) draw(progress); if (timeFraction < 1) { requestAnimationFrame(animate); } }); } شيفرة الملف index.html: <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <style> progress { width: 5%; } </style> <script src="animate.js"></script> </head> <body> <progress id="elem"></progress> <script> elem.onclick = function() { animate({ duration: 1000, timing: function(timeFraction) { return timeFraction; }, draw: function(progress) { elem.style.width = progress * 100 + '%'; } }); }; </script> </body> </html> ستكون النتيجة كالتالي: وإليك الشيفرة المستخدمة: animate({ duration: 1000, timing(timeFraction) { return timeFraction; }, draw(progress) { elem.style.width = progress * 100 + '%'; } }); يمكننا بهذا الأسلوب تنفيذ أي دوال توقيت ورسم على خلاف CSS، ولا ترتبط دوال التوقيت بمنحني بيزيه فقط، كما يمكن للدالة draw أن تتخطى الخصائص إلى إنشاء عناصر جديدة لرسوميات نحتاجها، مثل الألعاب النارية. دوال التوقيت اطلعنا في الفقرات السابقة على أبسط الدوال وهي الدالة الخطية، لنرى الآن بعض الدوال الأخرى، حيث سنجرب بعض الحركات الانتقالية باستخدام دوال توقيت مختلفة. دالة القوة من الدرجة n يمكن استعمال progress بدلالة القوة من الدرجة n لتسريع الحركة، مثل الدالة التربيعية (أي من الدرجة 2): function quad(timeFraction) { return Math.pow(timeFraction, 2) } إليك الرسم البياني: لترى النتيجة انقر على الشكل التالي: كما يمكنك استعمال الدالة التكعيبية (من الدرجة 3)، وسترى أن سرعة الحركة ستزداد بزيادة درجة القوة، إليك نموذجًا تكون فيه progress من الدرجة 5: الدالة المثلثية القطعية arc صيغة الدالة: function circ(timeFraction) { return 1 - Math.sin(Math.acos(timeFraction)); } الرسم البياني: المثال النموذج: دالة إطلاق السهم back عند اطلاق السهم bow shooting فسنسحب وتر القوس ثم نحرره، وخلافًا للدالتين السابقتين، ستعتمد الدالة على معامل إضافي x هو ثابت المرونة elasticity coefficient، والذي يُعرِّف المسافة التي نسحب بها وتر القوس: function back(x, timeFraction) { return Math.pow(timeFraction, 2) * ((x + 1) * timeFraction - x) } الخط البياني للدالة عندما x = 1.5: المثال النموذجي عند نفس القيمة للمعامل x: دالة الارتداد bounce عندما نرمي كرةً فستسقط للأسفل وترتد عدة مرات ثم تتوقف. تسلك الدالة bounce هذا السلوك تمامًا لكن بترتيب معكوس، حيث يبدأ الارتداد مباشرةً، وتستخدم هذه الدالة بعض الثوابت الخاصة: function bounce(timeFraction) { for (let a = 0, b = 1, result; 1; a += b, b /= 2) { if (timeFraction >= (7 - 4 * a) / 11) { return -Math.pow((11 - 6 * a - 11 * timeFraction) / 4, 2) + Math.pow(b, 2) } } } إليك نموذجًا يستخدم دالة الإرتداد: دالة الحركة المرنة elastic إليك دالةً أخرى "مرنةً" تقبل معاملًا إضافيًا x يضبط المجال الابتدائي للحركة: function elastic(x, timeFraction) { return Math.pow(2, 10 * (timeFraction - 1)) * Math.cos(20 * Math.PI * x / 3 * timeFraction) } الخط البياني للدالة عندما x=1.5: إليك نموذجًا عن استخدام الدالة: الدوال بترتيب معكوس تعرفنا حتى اللحظة على دوال التوقيت التي تُعرف بتحويلات الدخول السهل easeIn، لكننا قد نحتاج أحيانًا إلى عرض الحركة بترتيب معكوس. تُنفَّذ هذه الحركات بالتحويل الذي يُعرف باسم الخروج السهل easeOut. التحويل easeOut تُوضع الدالة timing في هذا التحويل ضمن المُغلِّف timingEaseOut: timingEaseOut(timeFraction) = 1 - timing(1 - timeFraction) بعبارة أخرى لدينا دالة التحويل makeEaseOut التي تقبل دالة توقيت نظاميةً وتعيد المُغلّف الذي يحيط بها: // accepts a timing function, returns the transformed variant function makeEaseOut(timing) { return function(timeFraction) { return 1 - timing(1 - timeFraction); } } يمكن على سبيل المثال اختيار الدالة bounce التي شرحناها سابقًا وتطبيقها: let bounceEaseOut = makeEaseOut(bounce); وهكذا لن تكون الحركة الارتدادية في بداية الحركة بل في نهايتها، وستبدو الحركة أفضل: شيفرة الملف style.css: #brick { width: 40px; height: 20px; background: #EE6B47; position: relative; cursor: pointer; } #path { outline: 1px solid #E8C48E; width: 540px; height: 20px; } شيفرة الملف index.html: <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <link rel="stylesheet" href="style.css"> <script src="https://js.cx/libs/animate.js"></script> </head> <body> <div id="path"> <div id="brick"></div> </div> <script> function makeEaseOut(timing) { return function(timeFraction) { return 1 - timing(1 - timeFraction); } } function bounce(timeFraction) { for (let a = 0, b = 1, result; 1; a += b, b /= 2) { if (timeFraction >= (7 - 4 * a) / 11) { return -Math.pow((11 - 6 * a - 11 * timeFraction) / 4, 2) + Math.pow(b, 2) } } } let bounceEaseOut = makeEaseOut(bounce); brick.onclick = function() { animate({ duration: 3000, timing: bounceEaseOut, draw: function(progress) { brick.style.left = progress * 500 + 'px'; } }); }; </script> </body> </html> وستكون النتيجة: سنرى هنا كيف سيغيّر التحويل سلوك الدالة، إذ ستعرَض التأثيرات الموجودة في بداية الحركة -مثل الارتداد- في النهاية، ففي الشكل التالي ستجد الارتداد الاعتيادي باللون الأحمر، والارتداد وفق تحويل الخروج السهل باللون الأزرق. الارتداد الاعتيادي: يرتد الكائن عند القاع، ثم يقفز بحدّة إلى القمة في النهاية. باستخدام easeOut الخروج السهل: يقفز أولًا إلى القمة ثم يرتد هناك. التحويل easeInOut يمكن أن نُظهر التأثير المطلوب في بداية ونهاية الحركة معًا، ويُدعى هذا التحويل بالدخول والخروج السهل easeInOut. سنحسب حالة الحركة باعتماد تابع توقيت ما كالتالي: if (timeFraction <= 0.5) { // نصف الحركة الأول return timing(2 * timeFraction) / 2; } else { // النصف الثاني للحركة return (2 - timing(2 * (1 - timeFraction))) / 2; } شيفرة المُغلِّف: function makeEaseInOut(timing) { return function(timeFraction) { if (timeFraction < .5) return timing(2 * timeFraction) / 2; else return (2 - timing(2 * (1 - timeFraction))) / 2; } } bounceEaseInOut = makeEaseInOut(bounce); إليك مثالًا نموذجيًا: شيفرة الملف style.css: #brick { width: 40px; height: 20px; background: #EE6B47; position: relative; cursor: pointer; } #path { outline: 1px solid #E8C48E; width: 540px; height: 20px; } شيفرة الملف index.html: <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <link rel="stylesheet" href="style.css"> <script src="https://js.cx/libs/animate.js"></script> </head> <body> <div id="path"> <div id="brick"></div> </div> <script> function makeEaseInOut(timing) { return function(timeFraction) { if (timeFraction < .5) return timing(2 * timeFraction) / 2; else return (2 - timing(2 * (1 - timeFraction))) / 2; } } function bounce(timeFraction) { for (let a = 0, b = 1, result; 1; a += b, b /= 2) { if (timeFraction >= (7 - 4 * a) / 11) { return -Math.pow((11 - 6 * a - 11 * timeFraction) / 4, 2) + Math.pow(b, 2) } } } let bounceEaseInOut = makeEaseInOut(bounce); brick.onclick = function() { animate({ duration: 3000, timing: bounceEaseInOut, draw: function(progress) { brick.style.left = progress * 500 + 'px'; } }); }; </script> </body> </html> وستكون النتيجة: يدمج التحويل كائنين رسوميين معًا، وهما التحويل easeIn (الاعتيادي) في النصف الأول للحركة، والتحويل easeOut (المعكوس) للنصف الثاني. سنرى التأثير بوضوح عند الموازنة بين التحويلات الثلاث easeIn وeaseOut وeaseInOut عند تطبيقها على دالة التوقيت circ: easeIn: باللون الأحمر. easeOut: باللون الأخضر. easeInOut: باللون الأزرق. كما نرى طبقنا على النصف الأول من الحركة easeIn، وعلى النصف الآخر easeOut، لذا ستبدأ الحركة وتنتهي بنفس التأثير. دالة draw أكثر تميزًا يمكننا القيام بأكثر من مجرد تحريك العنصر، وكل ما علينا فعله هو كتابة شيفرة مناسبة للدالة draw، إليك طريقةً لإظهار ارتداد أثناء كتابة نص مثلًا: شيفرة الملف style.css: textarea { display: block; border: 1px solid #BBB; color: #444; font-size: 110%; } button { margin-top: 10px; } شيفرة الملف index.html: <!DOCTYPE HTML> <html> <head> <meta charset="utf-8"> <link rel="stylesheet" href="style.css"> <script src="https://js.cx/libs/animate.js"></script> </head> <body> <textarea id="textExample" rows="5" cols="60">He took his vorpal sword in hand: Long time the manxome foe he sought— So rested he by the Tumtum tree, And stood awhile in thought. </textarea> <button onclick="animateText(textExample)">Run the animated typing!</button> <script> function animateText(textArea) { let text = textArea.value; let to = text.length, from = 0; animate({ duration: 5000, timing: bounce, draw: function(progress) { let result = (to - from) * progress + from; textArea.value = text.substr(0, Math.ceil(result)) } }); } function bounce(timeFraction) { for (let a = 0, b = 1, result; 1; a += b, b /= 2) { if (timeFraction >= (7 - 4 * a) / 11) { return -Math.pow((11 - 6 * a - 11 * timeFraction) / 4, 2) + Math.pow(b, 2) } } } </script> </body> </html> وستكون النتيجة كالتالي: خلاصة يمكن أن تساعدك JavaScript في تنفيذ الرسوميات التي لا تستطيع CSS التعامل معها، أو تلك التي تتطلب تحكمًا دقيقًا. تّنفّذ حركات JavaScript باستخدام التابع المدمج requestAnimationFrame الذي يسمح بإعداد دالة استدعاء تُشغَّل عندما يحضّر المتصفح نفسه لعملية إعادة الرسم Repaint. لن تُنفَّذ عملية إعادة الرسم إطلاقًا عندما تكون الصفحة في الخلفية، وبالتالي لن تعمل دالة الاستدعاء وسيُعلّق تنفيذ الحركة، ولن يكون هناك استهلاك للموارد. إليك الدالة المساعدة animate التي تحضّر معظم الرسوميات المتحركة التي تحتاجها: function animate({timing, draw, duration}) { let start = performance.now(); requestAnimationFrame(function animate(time) { // timeFraction goes from 0 to 1 let timeFraction = (time - start) / duration; if (timeFraction > 1) timeFraction = 1; // calculate the current animation state let progress = timing(timeFraction); draw(progress); // draw it if (timeFraction < 1) { requestAnimationFrame(animate); } }); } الخيارات هي: duration: الزمن الكلي للحركة مقدرًا بالميلي ثانية. timing: الدالة التي تحسب مقدار تقدم الحركة، حيث تقبل الدالة قيمًا زمنيةً هي نسبة بين 0 و1، وتعيد مقدار تقدم العملية. draw: الدالة التي ترسم الحركة. وبالطبع يمكن تحسين هذه الدوال وإضافة العديد من الأمور الأخرى، لكن لا يتكرر استخدام رسوميات JavaScript كثيرًا، فهي تستخدَم لإظهار شيء مهم لا لأمور تقليدية، لذا يمكنك إضافة الميزة التي تريدها عند الحاجة. يمكن أن تستخدم JavaScript أي دوال توقيت، وقد غطينا الكثير منها في هذا الفصل وطبقنا عليها تحويلات عدةً، إذًا لسنا مقيدين بمنحنيات بيزيه كما هي الحال في CSS. يمكننا استخدام draw لتحريك أي شيء وليس خصائص CSS فقط. مهام لإنجازها 1. تحريك كرة مرتدة أنشئ كرةً ترتد كما في المثال التالي: افتح المثال في بيئة تجريبية. الحل لجعل الكرة ترتد، سنسنتعمل الخاصية top والخاصية position:absolute مع الكرة والخاصية position:relative مع الملعب، ويكن إحداثيات أرضية الملعب هي field.clientHeight. تشير الخاصية top إلى بداية أعلى الملعب لذا يجب أن تتغير من 0 إلى field.clientHeight - ball.clientHeight وهو أدنى موضع يمكن أن تنخفض إليه حافة الكرة العلوية. يمكن تطبيق تأثير الارتداد باستعمال دالة التوقيت bounce في الوضع easeOut. إليك الشيفرة النهاية الناتجة: let to = field.clientHeight - ball.clientHeight; animate({ duration: 2000, timing: makeEaseOut(bounce), draw(progress) { ball.style.top = to * progress + 'px' } }); افتح الحل في بيئة تجريبية. 2. حرك الكرة المرتدة إلى اليمين اجعل الكرة ترتد إلى اليمين كالتالي: اكتب الشيفرة بحيث تكون مسافة الانتقال إلى اليمين هي 100px. الحل احتجنا في التمرين السابق إلى تحريك خاصية واحدة فقط، بينما سنحتاج في هذا التمرين إلى تحريك خاصية إضافية هي elem.style.left. نريد تغيير الاحداثيات الأفقية للكرة بزيادتها تدريجيًا نحو اليمين أثناء السقوط، لذا سنضيف حركة إضافة anumate يمكن أن نستعمل معها دالة التوقيت linear ولكن تبدو makeEaseOut(quad) أفضل بكثير. إليك الشيفرة النهاية الناتجة: let height = field.clientHeight - ball.clientHeight; let width = 100; // animate top (bouncing) animate({ duration: 2000, timing: makeEaseOut(bounce), draw: function(progress) { ball.style.top = height * progress + 'px' } }); // animate left (moving to the right) animate({ duration: 2000, timing: makeEaseOut(quad), draw: function(progress) { ball.style.left = width * progress + "px" } }); افتح الحل في بيئة تجريبية. ترجمة -وبتصرف- للفصل JavaScript Animation من سلسلة The Modern JavaScript Tutorial اقرأ أيضًا المقال السابق: إنشاء رسوم متحركة باستخدام CSS النسخة العربية الكاملة لكتاب: التحريك عبر CSS iframe { border: 1px solid #e7e5e3 !important; width: 100%; } iframe div#path { margin: auto; }1 نقطة