لوحة المتصدرين
المحتوى الأكثر حصولًا على سمعة جيدة
المحتوى الأعلى تقييمًا في 12/19/15 في كل الموقع
-
تعرَّفنا في المقال السّابق على العنصر Canvas الذي أُضيف إلى HTML5 ليوفّر أداة ومساحة لرسم الأشكال والتصاميم باستخدام جافاسكربت. سنتعلم في هذا الدّرس كيفية رسم الأشكال على Canvas باستخدام جافا سكربت مثل الدوائر، المثلَّثات والمستطيلات وسنتعرف على المنحنيات Curves لرسم أشكال أكثر تعقيدًا. الشبكة The grid إن أي عنصر يتم إضافته أو رسمه على Canvas يُحَدّد موقعه بواسطة الزَّاوية اليسارية العليا (0, 0) أي بإحداثيات (x, y) بحيث أنه يبعد عن المركز (0, 0) بمقدار (x, y). رسم المستطيلات Rectangles توفر canvas ثلاث دوال لرسم المستطيلات وجميعها تأخذ معاملات argumrnts مماثلة. الإحداثيات (x, y) تحدد موقع المستطيل بالنسبة للمركز (0, 0) والذي يحدَّد بالزَّاوية اليسارية العليا للـ Canvas، العرض width والطول height تحددان قياس المستطيل. الدَّالة ()fillRect ترسم مستطيلًا ذي مساحة لونية solid color. الدَّالة ()strokeRect ترسم مستطيلًا Storke (مُفرغًا) ذي حواف فقط outline. الدَّالة ()clearRect تقوم بمسح مستطيل محدّد بالمعاملات x, y) ،width ،height) أي تجعله شفافًا Transparent. ولا ننسى طبعا الدَّالة ()draw والتي تدير جميع عمليات الرَّسم على الـ canvas في الجافاسكربت. سنرى كيفية رسم المستطيلات باستخدام الدَّوال الثلاث أعلاه. السكربت التالي يرسم ثلاثة مستطيلات بإحداثيات وقياسات مختلفة : <script type="application/javascript"> function draw() { var canvas = document.getElementById("canvas"); if (canvas.getContext) { var ctx = canvas.getContext("2d"); ctx.fillStyle = "rgb(200,0,0)"; ctx.fillRect(10, 10, 200, 200); ctx.clearRect(30, 30, 150, 150); ctx.strokeRect(50, 50, 60, 60); } } </script> باستخدام ()fillRect تم رسم مستطيل ذو مساحة لونية حمراء بقياس 200*200 عند الإحداثيات (10,10). باستخدام ()clearRect تم رسم مستطيل بلا لون (شفاف) بقياس 150*150 عند الإحداثيات (30,30). باستخدام ()storkRect تم رسم مستطيل stroke مُفرغ ذو حواف بقياس 60*60 عند الإحداثيات (50,50). رسم المسارات Paths المسارات paths هي عبارة عن مجموعة من النقاط متصلة مع بعضها البعض بواسطة خطوط صغيرة segments لتقوم بتشكيل رسومات مختلفة كأشكال منحنية، أشكال هندسية…الخ. يمكن أن يكون المسار مفتوحًا مثل نصف دائرة او مغلقًا كالمثلَّث. هناك 4 خطوات أساسية لرسم المسارات حيث تُنفّذ مجموعة من الدَّوال بالتّرتيب للحصول على المسار بالشكل المطلوب. ()beginPath تقوم هذه الدَّالة بإنشاء المسار بحيث يتم رسم المسار وتخزين نقاطه في قائمة List. the methods هي مجموعة من الدَّوال التي تقوم بإنشاء أشكال أساسية مثل الدَّالة arc التي ترسم قوس والدّالة lineTo التي ترسم خط مستقيم. ()moveTo تقوم في كل مرة برسم نقطة انطلاق جديدة لبدء الرَّسم منها. ()closePath تقوم بإغلاق المسار ليتم الرَّسم خارج المسار بعدها أي البدء بمسار جديد. ()stroke تحول المسار المرسوم إلى شكل مُفرَّغ ذو حواف أي دون ملأ المسار. ()fill تحول المسار المرسوم إلى مسار ممتلئ بمساحة لونية solid. الخطوة الأولى لإنشاء مسار path هي استدعاء الدَّالة ()beginPath (بشكل ضمني المسارات تُخزَّن بشكل مسارات جزئية في مصفوفة أو قائمة List مثل خطوط أو منحنيات..الخ) والتي بمجملها مسؤولة عن تكوين الشكل. في كل مرة تتم فيها استدعاء الدَّالة ()beginPath يتم فيها إعادة إنشاء مصفوفة أو قائمة List جديدة ويمكننا البدء برسم شكل جديد. الخطوة الثانية هي استدعاء إحدى الدَّوال التي تقوم بتحديد المسار الذي سيُرسم مثل الدَّالة ()moveTo أو الدَّالة ()lineTo. الخطوة الثالثة هي استدعاء إحدى الدالتين ()storke أو ()fill. الخطوة الرابعة وهي خطوة اختيارية يتم فيها استدعاء الدَّالة ()closePath هذه الدَّالة تقوم بإغلاق الشكل عن طريق رسم خط مستقيم من النُّقطة الحالية التي توقف عندها الرَّسم إلى نقطة البداية التي بدأ عندها رسم المسار. ملاحظات: في حين كان الشكل قد أُغلق أثناء الرَّسم أو بقيت نقطة واحدة في القائمة List فهذه الدَّالة لن تقوم بعمل أي شيء. عند استدعاء الدَّالة ()fill فإن الأشكال المفتوحة ستُغلق تلقائيًّا أي لن يكون هناك داعي لاستدعاء الدَّالة ()closePath ولكن لا تنطبق هذه الحالة عند استدعاء الدَّالة ()storke. رسم مثلث اعتمادًا على خطوات إنشاء المسارات أعلاه سأقوم بإنشاء مسار مثلَّث كما في السكربت التالي: <script type="application/javascript"> function draw() { var canvas = document.getElementById("canvas"); if (canvas.getContext) { var ctx = canvas.getContext("2d"); ctx.beginPath(); ctx.moveTo(100, 100); ctx.lineTo(300, 200); ctx.lineTo(100, 200); ctx.fillStyle = "rgb(200,0,180)"; ctx.fill(); ctx.closePath(); ctx.beginPath(); ctx.moveTo(100, 300); ctx.lineTo(400, 300); ctx.lineTo(400, 200); ctx.fillStyle = "rgb(140,50,80)"; ctx.fill(); } } </script> قمت بإنشاء مثلَّثين الأول عند النُّقطة (100, 100)، رسم خط مستقيم بواسطة الدَّالة ()lineTo إلى النُّقطة (300, 200)، خط مستقيم إلى النُّقطة (100, 200) ثم تحديد اللّون عن طريق الدَّالة ()fillStyle وبالنهاية استدعاء الدَّالة ()fill ليتم تلوين المسار والحصول على شكل مثلَّث. كذلك الأمر بالنسبة للمثلَّث الثاني. عند تشغيل المتصفّح يظهر المثلَّثان بهذا الشكل: الرسم بتحريك القلم moving pen تخيل أنك تقوم برسم لوحة فنية كم مرة ستحتاج لترك نقطة رسم وتحريك القلم للبدء من نقطة جديدة، هذا ما تقوم به الدَّالة ()moveTo أي أنها تقوم بنقل نقطة بدء الرَّسم إلى نقطة (x, y) جديدة. عند إنشاء canvas أو عند استدعاء الدَّالة ()beginPath ستحتاج إلى استدعاء الدَّالة ()moveTo لتحديد نقطة البداية التي ستبدأ عندها الرَّسم. أو عندما تكون بحاجة لرسم مسارات متقطعة. للتوضيح أكثر سأقوم برسم وجه ضاحك smiley face وتلوينه كما في السكربت التالي: <script type="application/javascript"> function draw() { var canvas = document.getElementById('canvas'); if (canvas.getContext) { var ctx = canvas.getContext('2d'); ctx.beginPath(); ctx.fillStyle = "rgb(0, 0, 0)"; ctx.arc(75, 75, 50, 0, Math.PI * 2, true); ctx.stroke(); ctx.closePath(); ctx.beginPath(); ctx.fillStyle = "rgb(250, 250, 0)"; ctx.arc(75, 75, 50, 0, Math.PI * 2, true); ctx.fill(); ctx.closePath(); ctx.beginPath(); ctx.fillStyle = "rgb(250, 0, 0)"; ctx.moveTo(110, 75); ctx.arc(75, 75, 35, 0, Math.PI, false); ctx.fill(); ctx.closePath(); ctx.moveTo(65, 65); ctx.beginPath(); ctx.fillStyle = "rgb(0, 0, 0)"; ctx.arc(60, 65, 5, 0, Math.PI * 2, true); ctx.fill(); ctx.closePath(); ctx.beginPath(); ctx.moveTo(95, 65); ctx.fillStyle = "rgb(0, 0, 0)"; ctx.arc(90, 65, 5, 0, Math.PI * 2, true); ctx.fill(); ctx.closePath(); } } </script> يحتوى الشكل على 4 مسارات مغلقة: الإطار الخارجي للوجه، الوجه، الفم، العين اليمنى، العين اليسرى. لاحظ أنني قمت باستدعاء الدَّالة ()beginPath أربع مرات ولم أكن بحاجة لاستدعاء الدَّالة ()closePath عندما رسمت الإطار بالرغم من أنه stroke وذلك بسبب تقاطع نقطة النهاية مع البداية. أيضًا عند رسم الأشكال solid لم أحتج لاستدعاء الدَّالة ()closePath وذلك لأن الدَّالة ()fill تقوم بإغلاق المسار بشكل تلقائي لتلوينه. الخطوط Lines تُستخدم الدَّالة ()lineTo لرسم خطوط مستقيمة بحيث ترسم الخط من النُّقطة الحالية إلى نقطة محددة بـ (x, y). النقطة الحالية تتعلق بآخر مسار تم رسمه (أي أن النُّقطة الأخيرة لرسم المسار الأول هي نقطة بداية رسم المسار الثاني) يمكنك تغيير النُّقطة الحالية عبر استدعاء الدَّالة ()moveTo كما شرحنا في المثال السابق. لنقم بعمل مثال آخر لرسم مثلَّثين أحدهما solid والآخر stroke باستخدام الدالتين ()lineTo و ()moveTo واستدعاء الدَّالة ()lineTo مرتين لكل عملية رسم مثلَّث كما في السكربت التالي: <script> function draw() { var canvas = document.getElementById('canvas'); if (canvas.getContext) { var ctx = canvas.getContext('2d'); // Filled triangle ctx.beginPath(); ctx.moveTo(100, 100); ctx.lineTo(180, 100); ctx.lineTo(100, 180); ctx.fill(); // Stroked triangle ctx.beginPath(); ctx.moveTo(125, 125); ctx.lineTo(125, 45); ctx.lineTo(45, 125); ctx.closePath(); ctx.stroke(); } } </script> قمت باستدعاء الدَّالة ()beginPath عند البدء في رسم الشكل ثم استدعاء الدَّالة ()moveTo للانتقال لنقطة بداية الرَّسم. ثم بعد ذلك استدعاء الدَّالة ()LineTo مرّتين لرسم المثلَّث بالإحداثيات المناسبة. الآن استدعاء الدَّالة ()closePath عند الانتهاء من رسم المثلَّث من نوع storke لإغلاق المسار لأنه في حال عدم استدعاء هذه الدَّالة سيقوم برسم خطين فقط وليس مثلَّثا كاملًا. الأقواس Arcs يتم رسم الأقواس باستخدام الدالتين ()arc أو ()arcTo. تقوم الدالة (arc(x, y, radius, startAngle, endAngle, anticlockwise برسم قوس عند النُّقطة (x, y) بمقدار القطر radius r ببداية الزَّاوية startAngle وانتهاءً بالزَّاوية endAngle وبالاتجاه anticlockwise (القيمة الافتراضية تكون مع اتجاه عقارب الساعة clockwise). تقوم الدالة (arcTo(x1, y1, x2, y2, radius برسم قوس بمجموعة نقاط وقطر radius يتصل بالنُّقطة السابقة بواسطة خط مستقيم. إنَّ الدَّالة ()arcTo تأخذ 5 معاملات arguments: (x, y) وهما إحداثيي مركز الدائرة التي سيرسم عندها القوس القطر raduis هو قطر الدائرة المعاملان startAngle و endAngle يُحدّدان بداية ونهاية نقاط القوس بالراديان radians على طول قوس الدائرة حيث أنها تقاس من المحور x المعامل anticlockwise هو متغير منطقي Boolean عندما يأخذ القيمة true سيتم رسم القوس عكس اتجاه عقارب الساعة وإلا سيتم رسم القوس باتجاه عقارب الساعة. ملاحظة: الزَّوايا في الدَّالة ()arc تقاس بالراديان radians وليس بالدّرجات، للتحويل من الدّرجات للراديان يمكنك استخدام السكربت: radians = (Math.PI/180)*degrees سأقوم بعرض مثال يشرح طريقة رسم مجموعة من 12 قوسًا بزوايا مختلفة، حيث ستُعرض الأقواس على شكل صفوف (أسطر وأعمدة) في كل صف ثلاث أقواس. سيتم إنشاء حلقتي تكرار وتطبيقهما على أسطر وأعمدة الأقواس. لكل مسار قوس سيتم استدعاء ()beginPath في السكربت لإنشاء مسار جديد في كل مرّة لرّسم شكل جديد. قمت بتخزين كل معامل للدالة arc ضمن متغير لتسهيل استخدامها عند استدعاء الدَّالة. القطر radius وزاوية البداية startAngle هما ثوابت. أمّا زاوية النّهاية endAngle تبدأ من 180 درجة (نصف دائرة) في العمود الأول. وتزداد بمقدار 90 درجة لتصل إلى دائرة كاملة في العمود الأخير. في السّطر الأوّل والثّالث سيتم رسم الأقواس باتجاه عقارب الساعة، وفي السّطر الثّاني والرّابع سيتم رسم الأقواس عكس اتجاه عقارب الساعة. أخيرًا الشرط if سيقوم بعرض أقواس مُفرغة Stroke في الجزء العلوي من الصّفوف وأقواس ذات مساحة لونية solid في الجزء السُّفلي من الصّفوف. سنكون بحاجة إلى canvas بقياسات 150*200. function draw() { var canvas = document.getElementById(‘canvas’); if (canvas.getContext) { var ctx = canvas.getContext(‘2d’); for (var i = 0; i < 4; i++) { for (var j = 0; j < 3; j++) { ctx.beginPath(); var x = 25 + j * 50; var y = 25 + i * 50; var radius = 20; var startAngle = 0; var endAngle = Math.PI + (Math.PI * j) / 2; var anticlockwise = i % 2 == 0 ? false : true; ctx.arc(x, y, radius, startAngle, endAngle, anticlockwise); if (i > 1) { ctx.fill(); } else { ctx.stroke(); } } } } } المنحنيات التكعيبية والتربيعية Cubic and Quadratic Curves تخيّل أنّك تريد إنشاء قوس مائل أو قوس بقمة حادة أو أي نوع من الأقواس المعقدة، توفّر لك الدَّالة ()quadraticCurveTo إمكانيّة رسم أقواس ومنحنيات تربيعية Quadratic Curves والدَّالة ()bezierCurveTo تقوم برسم أقواس أو منحنيات تكعيبية cubic أو ما يعرف بـBézier Curves منحنيات بيزيير. 1- رسم منحني تربيعي تقوم الدالة (quadraticCurveTo(cp1x, cp1y, x, y برسم منحني بيزيير Bézier تربيعي من النُّقطة الحاليّة إلى نقطة معيّنة محددة بـ (x, y) باستخدام نقطة تحكم control point المحدّدة بـ cp1x و cp1y. تقوم الدَّالة (bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y برسم منحني بيزيير Bézier تكعيبي cubic باستخدام النّقاط المتحكّمة عن طريق (cp1x, cp1y) و (cp2x, cp2y). الصورة التّالية توضّح الفرق بين المنحنيين Quadratic و cubic: لاحظ أن منحني Bézier من الدّرجة الرّابعة لديه نقطة بداية ونقطة نهاية (النقاط الزرقاء) ونقطة تحكم واحدة (النُّقطة الحمراء) في حين أن منحني Bézier من الدرجة الثالثة لديه نقطتي تحكم. المعاملين x و y في كلا الدّالتين هما إحداثيات نقطة النّهاية. المعاملين cp1x و cp1y هما إحداثيات نقطة التحكم الأولى، المعاملين cp2x و cp2y هما إحداثيات نقطة التحكم الثانية. لنأخذ مثالًا عن كيفية إنشاء منحني Bézier تربيعي سيكون المثال مسلي بعض الشيء إذ أنني سأقوم بإنشاء بالون محادثة speech balloon: function draw() { var canvas = document.getElementById('canvas'); if (canvas.getContext) { var ctx = canvas.getContext('2d'); ctx.beginPath(); ctx.moveTo(75, 25); ctx.quadraticCurveTo(25, 25, 25, 62.5); ctx.quadraticCurveTo(25, 100, 50, 100); ctx.quadraticCurveTo(50, 120, 30, 125); ctx.quadraticCurveTo(60, 120, 65, 100); ctx.quadraticCurveTo(125, 100, 125, 62.5); ctx.quadraticCurveTo(125, 25, 75, 25); ctx.stroke(); } } تقوم الدَّالة ()quadraticCurveTo برسم منحني بالإحداثيات ونقطة التحكم المناسبة عند استدعائها بالقيم وبالترتيب أعلاه: 2- رسم منحي تكعيبي في المثال التالي شرح استخدام الدَّالة (bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y لرسم منحنيات من الدرجة الثالثة. تفيدنا هذه الدَّالة في رسم أشكال أكثر تعقيدًا لنأخذ مثلًا شكل القلب: function draw() { var canvas = document.getElementById(‘canvas’); if (canvas.getContext) { var ctx = canvas.getContext(‘2d’); ctx.beginPath(); ctx.fillStyle = "rgb(200,0,0)"; ctx.moveTo(75, 40); ctx.bezierCurveTo(75, 37, 70, 25, 50, 25); ctx.bezierCurveTo(20, 25, 20, 62.5, 20, 62.5); ctx.bezierCurveTo(20, 80, 40, 102, 75, 120); ctx.bezierCurveTo(110, 102, 130, 80, 130, 62.5); ctx.bezierCurveTo(130, 62.5, 130, 25, 100, 25); ctx.bezierCurveTo(85, 25, 75, 37, 75, 40); ctx.fill(); } } ينتج عن استدعاء الدَّالة (bezierCurveTo(cp1x, cp1y, cp2x, cp2y, x, y بالقيم وبالترتيب أعلاه الشكل: ها قد أنهينا تفاصيل إنشاء ورسم أشكال بطرق مختلفة على عنصر اللوحة Cancas، بوصولك إلى هنا تكون قد كونت معرفة ممتازة عن كيفية رسم مستطيلات، مثلثات، خطوط، أقواس ومنحنيات وأيضًا التعامل مع المسارات في Canvas. سنقوم في الدرس المقبل بـإنشاء شكل رسومي أكثر احترافية باستخدام كل تلك الأدوات معًا. المصادر1 نقطة
-
سنتعرّف في هذا الدّرس على أداة nw (سابقًا node-webkit) المُخصّصة لتطوير تطبيقات سطح المكتب العابرة للمنصات؛ باستخدام مُتصفّح كروميوم [Chromium [1 و node.js. حيث أصبح بالإمكان استخدام تقنيات الوِب الحديثة لتطوير برمجيات قادرة على الاستفادة من موارد النظام؛ كالتحكّّم بالملفات، استعمال قواعد البيانات وغيرها من الأمور. في هذا الدّرس سنتعلّم كيفية كتابة تطبيق لسطح المكتب باستخدام nw لتشغيل ملفّات الفيديو. لنبدأ. تثبيت node.js إذ كنت تَستخدم نظام التشغيل Windows أو Mac OS عندها استعمل معالج التثبيت الرسمي، أما في حال عملك على نظام لينكس فقم بتثبيتها من خلال مدير الحزم. تثبيت nw بعد تركيب node.js من خلال مدير حزم node.js نحتاج إلى تركيب nw، للقيام بذلك نفّذ ما يلي من خلال الطرفية: npm install nw -g أهلا بالعالم أنشئ مُجلدًا مُخصصًا لمشروعنا الأول باسم helloworld ثم أنشئ بداخله ملفّين: package.json إن سبق لك التطوير باستخدام node.js فستعرف بالتأكيد أن هذا هو الملف الخاص بمعلومات و خصائص التطبيق أو الحزمة، يمكنك إنشاءه بسهولة من خلال سطر الأوامر: npm init سنضيف إلى الملفّ بعض خصائص nw (حجم النافذة و الرابط للملف الرّئيسيّ) ليصبح شكل الملف بالكامل هكذا: { “name”: “helloworld”, “version”: “1.0.0”, “description”: “”, “main”: “index.html”, “window”: { “width”: 600, “height”: 400 }, “scripts”: { “test”: “echo \”Error: no test specified\” && exit 1” }, “author”: “hsoubAcademy”, “license”: “MIT” } index.html هو ملف nw الرئّيسيّ الذي قمنا بتحديده من ملف الحزمة (package.json)، سنُنشئ مُستند بسيط لطباعة أهلًا بالعالم. تشغيل التطبيق من خلال سطر الأوامر انتقل إلى ملف المشروع وشغّل nw: cd helloworld nw يجب أن تظهر لك نافذة بحجم 600X400px وبداخلها نص "أهلًا بالعالم". سياق شفرة javascript يوجد بـ nw سياقان لشِفرة javascript: سياق المُتصفّح وسياق node.js، عند استدعائك لملف javascript أو تشغيلك لشيفرة من خلال مستند html فإن هذه الشفرة تُمرر إلى المتصفح ليقرأها، أما عند تشغيلك لملفّ javascript من خلال خاصية node-main في ملفّ الحزمة (package.json) أو استدعائه من خلال الدّالّة require فإنه يُمرر إلى سياق node.js، حيث يوجد بعض الاختلافات الطفيفة بين هذين السياقين في الكتابة: 1. سياق المتصفح في هذا السياق تعمل الشيفرة بالأسلوب الذي تعمل به في المتصفح، المُتغيّر العام هو window مثلًا، هذه الشيفرة ستعمل بشكل صحيح فقط في سياق المُتصفح: myVar = “test”; // تعريف مُتغير بشكل عام alert(window.myVar); // إخراج نافذة بالمتغير ولتمرير المُتغيرات بشكل عام إلى سياق node.js يجب تعريفها كتابع للمُتغير window.global مثال ليعمل مثال: // ملف window.js // هذا الملف يجب أن يعمل من سياق المُتصفح window.global.myVar = “test”; // تعريف مُتغيّر بشكل عام إلى سياق المُتصفح require(“node.js”); // استدعاء ملف node.js بداخل سياق node.js // ملف node.js // هذا الملف يجب أن يعمل من سياق node.js window.alert(myVar); // عرض المُتغير الّذي تم تعريفه بشكل عام من سياق المُتصفح 2. سياق node.js في هذه السياق تعمل الشيفرة بأسلوب عملها باستخدام node.js، المُتغير العام هو global مثال: myVar = “test”; // تعريف مُتغير بشكل عام window.alert(global.myVar); // إخراج نافذة بالمتغير العام الّذي قمنا بتعريفه يُمكن استخدام سياق المتصفح والتمرير إليه من خلال المُتغير window. استدعاء الحزم التي كتبت للمتصفح بداخل سياق node.js عند استدعاء حزم تمت كتابتها للمُتصفح بداخل سياق node.js عن طريق الدّالّة require فقد لا تعمل، حيث تحدثنا سابقًا أن المتغيّر العام في سياق node.js هو global و ليس window مما يسبب مشكلة إن تم استدعاء أحد توابع window، عمومًا فالمثال لن يعمل في سياق node.js: var div = document.createElement(“div”); لجعل هذه الشيفرة تعمل يجب تعريف مُتغير document بشكل عام في سياق node.js: global.document = window.document; بشكل مبدئي سيجعل هذين السطرين أغلب الحزم تعمل: global.document = window.document; global.navigator = window.navigator; إن كنت تبحث عن حل تلقائي لنقل جميع المُتغيرات إلى سياق node.js (قد لا يُنصح بهذا الحل بسبب حذف المُتغيرات المتطابقة في الاسم): var Var; for(Var in window) if(Var != “require”) global[Var] = window[Var]; ملاحظة: لم ننقل مُتغير require لأن التابع window.require يستخدم global.require في استدعاء الحزم. لاحظ أيضًا أنه لا يمكن استدعاء حزمة nw.gui الخاصة بواجهة المستخدم من خلال سياق node.js عن طريق الدّالّة require فكما ذكرنا؛ التابع window.require يختلف عن global.require. هذا هو النص المصدري للتابع: window.require = function (name) { if (name == ‘nw.gui’) return nwDispatcher.requireNwGui(); return global.require(name); } وكما تلاحظ إن كان اسم الحزمة node.js فإنه يستخدم هذه الدّالّة لاستدعائها: nwDispatcher.requireNwGui(); إذًا لاستدعائها من خلال سياق node.js استخدم الدّالّة السابقة أو استخدم window.require. إنشاء تطبيق لتشغيل الفيديو ملفات المشروع هذه قائمة لملفات المشروع: ملف الحزمة (package.json) حجم النافذة الافتراضي هو 800x600px، الملفّ الرّئيسيّ هو index.html، مبدئيًا سيكون الملف بهذا الشكل: { “name”: “nw-video-player”, “version”: “1.0.0”, “description”: “تطبيق بسيط لتشغيل الفيديو”, “main”: “index.html”, “window”: { “width”: 800, “height”: 600 }, “scripts”: { “test”: “echo \”Error: no test specified\” && exit 1” }, “author”: “hsoubAcademy”, “license”: “MIT”, “dependencies”: { “videojs”: “^4.12.15” } } الملف الرئيسي index.html سنكتب مستند بسيط يحتوي على زر وعنصر، نضيف المشغّل ضمنه من خلال شيفرة javascript: <!doctype html> <html> <head> <meta charset="utf-8"> <title>تطبيق بسيط لتشغيل الفيديو</title> <!-- ملف شفرة js الرّئيسية للتطبيق --> <script src="src/app.js"></script> </head> <body> <button id="play">فتح</button> <div id="player"></div> </body> </html> نافذة فتح الملفات لا يوجد طريقة مباشرة لفتح الملفات باستخدام نافذة النظام، لكن يُمكننا استخدام مدخل input من نوع file لفتح الملفّات: لكن كخلاف المتصفح للمستخدم يُتاح لنا بعض الأشياء عند التطوير بـ nw كجلب المسار الكامل الحقيقي للملفّ، ويتاح لنا فتحه من خلال javascript: document.querySelector(“input”).click(); من خلال هذا سنكتب دالّة بسيطة لفتح ملفّات الفيديو وإرجاع مسار الملف مع إضافة بروتوكول file لاستخدامه من خلال المُتصفح، الدّالّة: // فتح ملف var openFile = function openFile (callback) { var input = window.document.createElement(“input”); input.setAttribute(“type”, “file”); input.setAttribute(“accept”, “.mp4, .ogg, .ogv, .webm”); input.addEventListener(“change”, function () { // عند إختيار ملف callback(“file://”+this.value); }); input.click() // فتح مُختار الملفات } تجربة استخدام: openFile(alert); مشغل الفيديو سنستخدم video.js لتسهيل تصميم المشغّل من خلال سطر الأوامر، اتجه إلى مجلّد المشروع ثم قم بتنصيب video.js من مدير الحزم الخاص بـnode.js: npm install videojs –save كما تحدثنا في بداية الدرس عن استدعاء الحزم في سياق node.js سنحتاج إلى كتابة هذين السطرين: global.document = window.document; global.navigator = window.navigator; من ثم سيمكننا استدعائها بشكل عادي: var videojs = require(“videojs”); من خلال هذا والدّالّة السابقة لفتح الملفات سنكتب دالّة لإنشاء مشغل فيديو من خلال مسار ملف الفيديو من ثم إضافته إلى عنصر المشغّل في المستند الذي كتبناه من قبل: var playVideo = function playVideo (src) { var videojs = require("videojs"), ext = /[^.]+$/.exec(src)[0], // صيغة الملفّ video = document.createElement("video"), // عنصر الفديو source = document.createElement("source"), // عنصر المصدر للفديو player = document.querySelector("#player"); // عنصر المشغل في وثيقة html ext = (ext == "ogv") ? "ogg" : ext; // ملفات ogg قد تملك صيغة ogv source.type = "video/"+ext.toLowerCase(); // نوع mime للفديو source.src = src; // مسار الفديو video.controls = true; // عناصر التحكّم video.autoplay = true; // تشغيل تلقائي video.classList.add("video-js", "vjs-default-skin"); // الclass الخاصة بvideojs video.appendChild(source); // إضافة عنصر المصدر إلى الفديو player.innerHTML = ""; // إزالة جميع العناصر السّابقة player.appendChild(video); // إضافة الفديو إلى وثيقة html videojs(video) // إستخدام video.js } مشكلة nw مع الصيغ مُغلقة المصدر: بشكل افتراضي سيمكنك تشغيل ملفات ogg و webm فقط لكن بسبب مشكلة مع التراخيص، لا تتضمن nw مشغّل لصيغة mp4 و الصوت mp3 اطلع على طريقة تضمين الملفّات المُشغلة. الآن تبقى فتح الملفّ عند الضغط على الزر: window.addEventListener(“load”, function () { window.document.querySelector(“button#play”).addEventListener(“click”, function () { openFile(playVideo) }); }); ليصبح كامل ملف app.js: "use strict"; global.document = window.document; global.navigator = window.navigator; var nwGui = require("nw.gui"), Window = nwGui.Window.get(); (function(window, nwGui, Window){ var maximized; // فتح ملف var openFile = function openFile (callback) { var input = document.createElement("input"); input.setAttribute("type", "file"); input.setAttribute("accept", ".mp4, .ogg, .ogv, .webm"); input.addEventListener("change", function () { // عند إختيار ملف callback("file://"+this.value); }); input.click() // فتح مُختار الملفات } // تشغيل فديو var playVideo = function playVideo (src) { var videojs = require("videojs"), ext = /[^.]+$/.exec(src)[0], // صيغة الملفّ video = document.createElement("video"), // عنصر الفديو source = document.createElement("source"), // عنصر المصدر للفديو player = document.querySelector("#player"); // عنصر المشغل في وثيقة html ext = (ext == "ogv") ? "ogg" : ext; // ملفات ogg قد تملك صيغة ogv source.type = "video/"+ext.toLowerCase(); // نوع mime للفديو source.src = src; // مسار الفديو video.controls = true; // عناصر التحكّم video.autoplay = true; // تشغيل تلقائي video.classList.add("video-js", "vjs-default-skin"); // الclass الخاصة بvideojs video.appendChild(source); // إضافة عنصر المصدر إلى الفديو player.innerHTML = ""; // إزالة جميع العناصر السّابقة player.appendChild(video); // إضافة الفديو إلى وثيقة html videojs(video) // إستخدام video.js } window.addEventListener("load", function () { // زر فتح فديو window.document.querySelector("button#play").addEventListener("click", function () { openFile(playVideo) }); }); }) (window, nwGui, Window); تصميم التطبيق بداخل مُستند html أضف مسار ملفّ css الافتراضي لـvideo.js الموجود داخل مجلد node_modules: ثم سنلغي شريط الأدوات الخاص بـnw بداخل ملف الحزمة (package.json) وبداخل العنصر window أضف ما يلي: “toolbar”: false من ثم سننشئ ملف تصميم src/style.css: html, body{ width: 100%; height: 100%; background: #ccc; direction: rtl; margin: 0 } /* زر التشغيل */ #play{ height: 25px; background: white; padding: 2px 20px; box-sizing: border-box; border: 1px #ccc solid } #play:hover{ box-shadow: inset 0 0 1px #333 } /* المُشغل */ #player{ background: black; width: 100%; height: calc(100% - 25px) } #player > .video-js{ width: 100% !important; height: 100% !important } إضافته من خلال مُستند html: كان من الأفضل استخدام قائمة النظام لعرض زر تشغيل الفيديو لكن nw لا تدعم الاتجاه من اليمين إلى اليسار بشكل كامل إلى الآن، لذا سنضيف السطر التالي إلى ملف الحزمة كي تظهر من اليمين إلى اليسار: “chromium-args”: “–lang=ar” بدلًا من ذلك سنقوم بإنشاء إطار مُخصص للنافذة لتبدو بشكلٍ أفضل في مختلف الأنظمة. تخصيص إطار النافذة بداخل ملف الحزمة (package.json) وبداخل عنصر window سنلغي الإطار الافتراضي: “frame”: false من ثم بداخل مستند html سنضيف أزرار النافذة في أول عنصر جسم الصفحة (body). سنضيف و نحذف بعض الخصائص من ملف src/style.css ليصبح شكل النافذة شبيه بنافذة نظام OS X: html, body{ width: 100%; height: 100%; background: #ccc; direction: rtl; margin: 0 } /* زر التشغيل */ #play{ -webkit-app-region: no-drag; height: 25px; background: white; padding: 2px 20px; box-sizing: border-box; border: 1px #ccc solid; position: absolute; right: 5px; top: 2px } #play:hover{ box-shadow: inset 0 0 1px #333 } /* المُشغل */ #player{ background: black; width: 100%; height: calc(100% - 25px) } #player > .video-js{ width: 100% !important; height: 100% !important } /* النافذة */ body{ box-sizing: border-box; border: #DDDDDC 5px solid } .window-toolbar{ -webkit-app-region: drag; background: -webkit-linear-gradient(#DDDDDC, #C2C2C2); height: 25px; direction: ltr; padding: 2px 5px; box-sizing: border-box } .window-toolbar > label.title{ position: absolute; left: 50%; transform: translate(-50%, 0) } .window-toolbar-button{ -webkit-app-region: no-drag; width: 12px; height: 12px; border-radius: 100%; display: inline-block; cursor: pointer; margin-right: 2px } .window-toolbar-button.close{ background: #FD4E4E } .window-toolbar-button.maximize{ background: #96D16F } .window-toolbar-button.minimize{ background: #F3BB55 } مُلاحظة: الخاصية webkit-app-region- المسؤولة عن جعل العنصر قابل للسحب والإفلات أيضًا يُمكن التحكّم بموقع النافذة من هذا العنصر لهذا استخدمناه في شريط أدوات النافذة لكن هذا العنصر لن يكون قابل للضغط أو المرور عليه لذلك يجب تعطيلها لعناصر التحكّم بداخله. لنكتب بعض الشيفرات بداخل ملفّ src/app.js لإضافة الحياة لشريط الأدوات. توفّر nw بعض التوابع للتحكم بالنافذة ما سنحتاجه للعمل: require(“nw.gui”).Window.get().close(); // إغلاق النافذة الحالية فقط require(“nw.gui”).App.quit(); // إغلاق التطبيق بجميع النوافذ require(“nw.gui”).Window.get().minimize(); // تصغير النافذة إلى شريط التطبيقات require(“nw.gui”).Window.get().maximize(); // ملء الشاشة بالنافذة require(“nw.gui”).Window.get().unmaximize(); // إرجاع النافذة أولًا زر الإغلاق: var nwGui = require(“nw.gui”); // زر إغلاق التطبيق window.document.querySelector(“.close”).addEventListener(“click”, function () { nwGui.App.quit(); }); ثانيًا زر إخفاء النافذة إلى شريط التطبيقات: var nwGui = require("nw.gui"), Window = nwGui.Window.get(); // زر تصغير النافذة إلى شريط التطبيقات window.document.querySelector(".minimize").addEventListener("click", function() { Window.minimize() }); زر ملء النافذة لكن أولًا سنضيف مراقب للحدثين maximize و unmaximize لمعرفة هل النافذة بكامل الحجم أو لا، حيث لا توفّر nw أيّة API لمعرفة ذلك: var nwGui = require(“nw.gui”), Window = nwGui.Window.get(), maximized = false; // مراقب للحدث maximize Window.on("maximize", function(){ maximized = true; }); // مراقب للحدث unmaximize Window.on("unmaximize", function(){ maximized = false; }); من خلال هذا وعند الضغط على زر الملئ إما أن تذهب النافذة لكامل الحجم أو تعود لحجمها الطبيعي: window.document.querySelector(“.maximize”).addEventListener(“click”, function () { maximized ? Window.unmaximize() : Window.maximize() }); يجب أن يكون كامل ملف src/app.js بهذا الشكل: "use strict"; global.document = window.document; global.navigator = window.navigator; var nwGui = require("nw.gui"), Window = nwGui.Window.get(); (function(window, nwGui, Window){ var maximized; // فتح ملف var openFile = function openFile (callback) { var input = document.createElement("input"); input.setAttribute("type", "file"); input.setAttribute("accept", ".mp4, .ogg, .ogv, .webm"); input.addEventListener("change", function () { // عند إختيار ملف callback("file://"+this.value); }); input.click() // فتح مُختار الملفات } // تشغيل فديو var playVideo = function playVideo (src) { var videojs = require("videojs"), ext = /[^.]+$/.exec(src)[0], // صيغة الملفّ video = document.createElement("video"), // عنصر الفديو source = document.createElement("source"), // عنصر المصدر للفديو player = document.querySelector("#player"); // عنصر المشغل في وثيقة html ext = (ext == "ogv") ? "ogg" : ext; // ملفات ogg قد تملك صيغة ogv source.type = "video/"+ext.toLowerCase(); // نوع mime للفديو source.src = src; // مسار الفديو video.controls = true; // عناصر التحكّم video.autoplay = true; // تشغيل تلقائي video.classList.add("video-js", "vjs-default-skin"); // الclass الخاصة بvideojs video.appendChild(source); // إضافة عنصر المصدر إلى الفديو player.innerHTML = ""; // إزالة جميع العناصر السّابقة player.appendChild(video); // إضافة الفديو إلى وثيقة html videojs(video) // إستخدام video.js } window.addEventListener("load", function () { // زر فتح فديو window.document.querySelector("button#play").addEventListener("click", function () { openFile(playVideo) }); // زر إغلاق التطبيق window.document.querySelector(".close").addEventListener("click", function () { nwGui.App.quit() }); // مراقب للحدث maximize Window.on("maximize", function(){ maximized = true; }); // مراقب للحدث unmaximize Window.on("unmaximize", function(){ maximized = false; }); // زر تصغير النافذة إلى شريط التطبيقات window.document.querySelector(".minimize").addEventListener("click", function() { Window.minimize() }); // زر الملء window.document.querySelector(".maximize").addEventListener("click", function () { maximized ? Window.unmaximize() : Window.maximize() }); }); }) (window, nwGui, Window); صورة للشكل النهائي: إن لم يظهر التطبيق بنفس الشكل فإليك ملفات التطبيق النهائية. بناء الملف التنفيذي لو أردنا إتباع الأسلوب التقليدي فنحن نحتاج إلى أنظمة التشغيل الثلاثة لبناء التطبيق في كل واحد منها على حدى، بدلًا من ذلك سنستخدم nwbuild لبناء التطبيق من خلال نظام تشغيل واحد إلى جميع أنظمة التشغيل. من مدير حزم npm قم بتركيب nwbuild : npm install nwbuild -g أنظمة التشغيل المتوفرة لـnwbuild: win32 # Windows 32bit win64 # Windows 64bit win # Windows 64bit مع 32bit osx32 # Mac OS 32bit osx64 # Mac OS 64bit osx # Mac OS 64bit مع 32bit linux32 # Linux 32bit linux64 # Linux 64bit linux # Linux 64bit مع 32bit ليعمل على أنظمة التشغيل الثلاث سنبنيه لـlinux ، osx64 و win32، اتّجه إلى مجلد التطبيق ونفّذ: nwbuild -p linux,osx64,win32 ./ سيعمل أولًا على تحميل ملفات البناء لأنظمة التشغيل من ثم بناء الملفات التنفيذية، ستلاحظ أن متوسط الحجم 50 ميغابايت للملفّ الواحد بسبب تضمين المتصفحات والملفات التشغيلية. التالي سيكون من الرائع تعلم react لبناء تطبيقات سطح مكتب رائعة باستخدام nw مع react. مصادر nw window nw App nw javascript contexts nw build هوامش 1 - كروميوم (Chromium) هو متصفح ويب مفتوح المصدر، يأخذ متصفح Google كروم الكود المصدري منه. المتصفحان يشتركان في أغلبية الشِفرة البرمجية والميزات، وإن كانت هناك بعض الاختلافات الطفيفة في ملامح كلا منهما وفي تراخيص الأستخدام أيضا. المصدر: ويكيبيديا.1 نقطة
-
يمكن أن يتسبب تخلّي العملاء عن الخدمة (أو ما يُعرف بـ "Customer Churn") بخسائر مادية كبيرة، سيعرّفك هذا المقال على آليات الحدّ من حدوث ذلك لتحافظ على أرباحك. في استطلاع رأي أُجري هذا العام سُئل أصحاب الشركات التجارية الصغيرة عن أكبر التحديات التي تواجههم، ما هي الإجابة الأولى برأيكم؟ جذب عملاء جدد. وطالما أن كسب العملاء الجدد يعتبر تحديًا كبيرًا، ينسى العديد من أصحاب الشركات أن الحفاظ على الزبائن الحاليين هو مكسب مهم، بل هدف أعلى أولوية من جذب عملاء جدد. يعدّ تخلي العملاء عن الخدمة (Customer churn) من أكبر مسببات فشل أي عمل تجاري، وقد تؤدّي أية زيادة طفيفة في نسبة العملاء المتخلين عن خدمتك لانخفاض أرباحك للنصف، يوضّح المثال التالي -من إعداد فريق Punchlime- تأثير هذا التخلي على كل من الإيرادات وتقدير مستقبل العمل: وبغض النظر عن الأرقام الواردة ثمة حقيقة لا شك فيها: يمكن أن يؤدي تخلي العملاء عن المنتج إلى سحق عملك في حال سمحت له بذلك. الأسباب الأربعة الشائعة لتخلي العملاء عن الخدمةإذا أمكنك تخيّل العملاء كالماء داخل وعاء، سيتسبّب وجود ثقوب أو ضعف فيه "لتسرّب" الماء، وسنغطّي في هذا المقال الأربعة أسباب الأكثر شيوعًا لحدوث ذلك، وكيف تتعامل مع كل سبب منها. 1- خدمة العملاء السيئةيفكّر العديد من أصحاب الشركات بـخدمة العملاء كما لو كانت تكلفة ينبغي تخفيضها لأقل قدر ممكن، عوضًا عن كونها استثمارًا ينبغي الزيادة فيه. وإليكم العقدة في الموضوع: إن كنت تفكر بخدمة الدعم الفني لديك كمركز للتكلفة، سيكون الأمر كذلك، وإن لم يكن تقديم خدمة عملاء مميزة على رأس أولويات عملك، ستصبح هذه الخدمة مركزًا لخسارتك: للأموال، وللعملاء. في دارسة أجرتها أوراكل تبيّن أن 9 من كل عشرة عملاء يتخلون عن الخدمة يفعلون ذلك عقب تجربة سيئة. وكما يمكن لخدمة الدعم الفني الرديئة أن تكلفك الكثير من الخسائر، بينت ذات الدراسة أن خدمة الدعم الفني الممتازة تعني ربحًا أكيدًا، إذ يبدي 86% من العملاء استعدادهم للدفع أكثر لقاء خدمة عملاء أفضل. لذا لن تحدّ خدمة الزبائن الجيدة من نسب تخلي العملاء عن منتجك فحسب، بل ستكسب عملك قابلية للمزيد من الأرباح، وسيدفع العملاء المال بسعادة. كيف يمكنك أن تقدم خدمة دعم فني أفضل؟ اعمل على تطوير مهارات فريق خدمة الدعم الفني.استعن ببعض نماذج البريد الإلكتروني الجاهزة للتعامل بنجاح مع أسوأ المواقف والتحديات التي تواجهك.تعلّم العبارات الرئيسية المهمّة في خدمة العملاء.استفد من نصائح خدمة استعادة العملاء للتعامل مع الغاضبين منهم.2- تهيئة المُستخدمين السيئة (Bad Onboarding)هناك مَعلمَان رئيسيّان في علاقة أي عميل بالخدمة التي تقدمها وهما: اللحظة التي سجّل فيها دخوله لمنتجك، واللحظة التي حصد فيها أول نجاح مع هذا المنتج. يحدث تخلّي عميلك عن الخدمة بين هاتين النقطتين، إذ قد يشعر بأنه تائه لا يفهم بعض الأمور، أو أنّه لم يحصّل على قيمة مضافة من المنتج، أو على الأقل فقد الاهتمام به. وعملية التهيئة Onboarding هي ما يمكن أن نسميه لمساعدة العميل على تجاوز المرحلة الأولى من استخدام المنتج ليصل للمرحلة الثانية، وهنا ستدفعه التهيئة السيئة والبطيئة للتخلي عنك بشكل كبير، وتبدّد جميع جهودك للحصول على هؤلاء العملاء الجدد ليتحوّلوا عنك عند أول عقبة. يمكنك أن تقيّد هذا الأمر وتقلّصه بالعمل على جعل انتقالهم من النقطة الأولى للثانية بأسرع وأسلس شكل متاح. كيف تحسّن تدفق عملية التهيئة الخاصة بمنتجك؟ يمكنك القراءة حول هذا الموضوع بشكل مكثّف، فثمة العديد من الدراسات والمقالات التي من شأنها إعطاءك أفكار لتجربة تهيئة أفضل لعميلك. 3- محدودية استمرار نجاح العملاءلا ينتهي عملك بمجرّد حصد الزبون للثمرة الأولى من استخدام منتجك، فهناك المئات من المتغيرات التي تتطلب متابعتك المستمرة، مثل التغييرات المطلوبة في المنتج، والارتباك الناتج عن إضافة ميزة جديدة أو طرح تحديثات للخدمة، بالإضافة للحضور المتزايد لمنتجات منافسة في السوق، إهمال كل هذه التحديات قد يؤدي في النهاية لخسارة عملائك. إن توقفّتْ أخبار منتجك عن الوصول لعملائك، وتوقّفتَ بدورك عن مساعدتهم للحصول على قيمة مضافة مع منتجك، ستساهم بذلك بجعل دورة حياة استخدام منتجك أقصر فأقصر. كيف تتأكد من استمرار نجاح عملائك مع منتجك؟ تعلم المزيد.يمكنك القراءة حول المقاييس التي تعتمدها بعض الشركات لتتبع نجاح العملاء مع منتجها، وطرق تحسين تجربة الاستخدام.4- أسباب طبيعيةلا يعني تخلي العميل عن منتجك فشلك على الدوام، فقد يحدث هذا لأسباب طبيعية، فمثلًا من الممكن أن يتسبب إفلاس الزبون بتخليه عن خدمتك، في بعض الأحيان يؤدي تغيير المناصب والوظائف في الشركات لتغيير الخدمات التي يتعاملون معها، وقد ينمو عميلك ويحتاج لمنتج أكبر مما لديك، أمور كهذه تحدث مع كل الشركات التجارية، لكن كونها طبيعية لا ينفي تأثيرها على إيراداتك، وعملك عليها سيحدّ من نسبة تأثيرها بالتأكيد. ما الذي يمكنك فعله حيال هذا الأمر؟ حدد نقاط حمراء ومقاييس تمكنك من ملاحظة أي زيادة في تخلي العملاء لهذه الأسباب قبل تفاقم المشكلة.قد تساعدك تنمية العميل المستمرة على فهم حاجات عملائك المتغيرة وأهدافهم، ما يمكنك من إدخالها في مخططاتك لمجاراتها.أجرِ بعض الاستطلاعات على عملائك لتعرف الأسباب الطبيعية التي تدفعهم للتخلي عن خدمتك، وفيما إذا كنت تستطيع فعل شيء للحد منها.نسبة تخلي عملاء أقل، أرباح أكثرتخلي العملاء هو واحدة من أكثر المقاييس ارتباطًا مباشرًا بأرباح أي منتج، وحالما تتعامل مع هذه المشكلة بنجاح ستضمن ارتفاعًا أكيدًا في إيرادات عملك. يكمن كل الأمر ببساطة في تحديد أماكن الثقوب التي تحدث تسرّبًا في دلوك، ومعرفة ما يجب القيام به لمعالجة هذه الفجوات. تُرجم بتصرّف عن مقال Why Customer Churn Happens, And What You Can Do About It لكاتبه Len Markidan.1 نقطة
-
ان كنتي تستخدمين لينكس ، فيمكنك تثبيت مشغل vlc والذي يدعم رفع الصوت الى 200% ايضا ان كنتي تستخدمين اوبونتو بواجهة يونتي فيمكنك رفع الصوت الى اكثر من 100% من خلال اعدادات الصوت في لوحة التحكم1 نقطة
-
أعمل على توزيعة دبيان التجريبية (9) بواجهة غنوم 3. هل هناك عميل في لينكس لحساب Google Drive؟ وما هي طرق الربط المتاحة؟1 نقطة
-
كما هو معلوم السيرة الذاتية لأيٍ منا بمثابة تعريف ووثيقة تعبّر عن مستواه العلمي والعملي، لذا أحببت تحويل سيرتي الذاتية -CV- من ملف نصي على برنامج وورد إلى وثيقة على LaTeX،وأربد عرض مهاراتي ومدة دراستي على عمود أفقي مع نص يصف المهارة والمدة ، بهذا الشكل -تقريبا-: كيف أستطيع الوصول إلى هذه النتيجة على LaTeX؟1 نقطة
-
لإنشاء Docker images لتطبيق PHP ثم رفعها إلى Docker Hub: 1- قم بتنصيب git وذلك لاستنساخ تطبيق PHP بسيط من Amazon GitHub repository إلى نظام التشغيل الخاص بك. a- تثبيت git: [ec2-user ~]$ sudo yum install -y git b- استنساخ تطبيق PHP إلى نظام التشغيل الخاص بك: [ec2-user ~]$ git clone https://github.com/awslabs/ecs-demo-php-simple-app2- تغيير الـ directories إلى المجلد ecs-demo-php-simple-app [ec2-user ~]$ cd ecs-demo-php-simple-app3- اختبر الملف Dockerfile في هذا المجلد (ملف Dockerfile هو عبارة عن manifest يصف ما هي الصورة image التي تريدها وما الذي تريد تنصيبه وتشغيله عليها). تستخدم ECS task definition صور الحاويات Doker images لتشغيل الحاويات Containers على الحاويات الافتراضية في الكتلة Cluster الخاصة بك. [ec2-user ecs-demo-php-simple-app]$ cat Dockerfile FROM ubuntu:12.04 # Install dependencies RUN apt-get update -y RUN apt-get install -y git curl apache2 php5 libapache2-mod-php5 php5-mcrypt php5-mysql # Install app RUN rm -rf /var/www/* ADD src /var/www # Configure apache RUN a2enmod rewrite RUN chown -R www-data:www-data /var/www ENV APACHE_RUN_USER www-data ENV APACHE_RUN_GROUP www-data ENV APACHE_LOG_DIR /var/log/apache2 EXPOSE 80 CMD ["/usr/sbin/apache2", "-D", "FOREGROUND"]4- قم بعمل Build لـ Docker image من DockerFile واستبدل الاسم my-dockerhub-username باسم مستخدم Docker Hub الخاص بك. [ec2-user ecs-demo-php-simple-app]$ docker build -t my-dockerhub-username/amazon-ecs-sample .5- شغّل docker images للتحقّق من أنه تم إنشاء الصورة بشكل صحيح وأن اسم الصورة يحتوى على المستودع repository الذي يمكنك إضافة اسم مستخدم Docker Hub الخاص بك. [ec2-user ecs-demo-php-simple-app]$ docker images REPOSITORY TAG IMAGE ID CREATED VIRTUAL SIZE my-dockerhub-username/amazon-ecs-sample latest 43c52559a0a1 12 minutes ago 258.1 MB ubuntu 12.04 78cef618c77e 3 weeks ago 133.7 MB6- قم بتشغيل الصورة التي بنيت حديثًا: [ec2-user ecs-demo-php-simple-app]$ docker run -p 80:80 my-dockerhub-username/amazon-ecs-sample7- افتح المتصفح وقم بالإشارة إلى الخادوم الذي يشغّل Docker ويستضيف الحاوية الخاصة بك. إن كنت تستخدم EC2 instance ستكون هذه قيمة DNS العامة للخادوم. والذي هو العنوان نفسه الذي تستخدمه للاتصال بالنسخة instance مع SSH. تأكد من أن مجموعة الأمان لديك تسمح بحركة المرور الواردة على المنفذ 80.إن كنت تقوم بتشغيل Docker محليًا على جهاز لينكس أشر متصفحك إلى http://localhost/إن كنت تستخدم boot2docker على جهاز ويندوز أو ماك فقم بإيجاد عنوان IP لـ VirtualBox VM التي تستضيف Docker.$ boot2docker ip 192.168.59.103 8- قم بإيقاف حاوية Docker بكتابة Ctrl + C 9- لرفع Docker image إلى حساب Docker Hub الخاص بك: a- سجل الدخول إلى حساب Docker الخاص بك. [ec2-user ecs-demo-php-simple-app]$ docker loginb- تحقق من أنك قد قمت بتسجيل الدخول بشكل صحيح. [ec2-user ecs-demo-php-simple-app]$ docker infoيجب أن يظهر لك "Username: my-dockerhub-username" في الخرج output c- عمل push للصورة image [ec2-user ecs-demo-php-simple-app]$ docker push my-dockerhub-username/amazon-ecs-sampleملاحظة: إن تلقيت خطأ "FATA[0012] Error pushing to registry: Authentication is required" تحقق من أنك تستخدم المستودع الذي يملك صلاحيات أو أذونات تسمح لك بعمل Push. كيف أنشئ Docker images وأرفعها إلى Docker Hub؟1 نقطة
-
لحذف كائن object في Amazon S3: 1- سجل الدخول إلى Amazon S3 Console https://console.aws.amazon.com/s3/ 2- اختر الملف الذي تريد حذفه من القائمة في محفظة التخزين Bucket وانقر عليه بالزر اليميني ثم اختر Delete ملاحظة: يمكنك استخدام Shift+ Ctrl لتحديد أكثر من ملف وتطبيق عملية الحذف على عدّة ملفات في وقت واحد. 3- ستظهر لك رسالة تأكيد اضغط على OK يمكنك تفريغ محفظة تخزين Bucket أي حذف كافة العناصر التي تحتويها دون حذف محفظة التخزين. 1- اختر محفظة التخزين التي تريد تفريغها وانقر عليها بالزر اليميني ثم اختر Empty Bucket أو يمكنك اختيار Empty Bucket من قائمة Actions 2- عندما تظهر لك رسالة تأكيد اكتب اسم محفظة التخزين التي ترغب بإفراغها ثم اضغط على Empty bucket لحذف محفظة تخزين مع كل العناصر التي تحتويها: 1- اختر محفظة التخزين التي تريد حذفها وانقر عليها بالزر اليميني ثم اختر Delete Bucket أو يمكنك اختيار حذف محفظة التخزين من القائمة Actions 2- عندما تظهر لك رسالة تأكيد اكتب اسم محفظة التخزين التي تريد حذفها ثم اضغط على Delete:1 نقطة
-
أولا يجب أن تعلم أن صفحة البيع أو صفحة لاندنج بيج كلاهما صفحة هبوط، فأي صفحة إنترنت تخصك هي صفحة هبوط بما أن هناك زائر هبط إليها. وأي صفحة هبوط موجودة لهدف معين، فبعضها يهدف لبيع منتج أو خدمة ما وهو ما يسمى بصفحة البيع، وهناك ما يهدف فقط لالتقاط قوائم بريدية أو لمجرد قراءة مقال ما وهذا ما يسمى بلاندنج بيج، أظن أنك قد عرفت الفرق بينهما الآن. المهم أن تكون لكل صفحة هبوط هدف معين، سواء بيع منتج أو خدمة، أو لضغط على إعلانات، أو لالتقاط قوائم بريدية، أي أن عدم وجود هدف يجعل من الصفحة غير مفيدة. ثانيا سنتعرف الآن على مكونات صفحة البيع كما جاء في سؤالك: - عرف بنفسك في البداية، وماهي صفتك، ولماذا يجب أن يثق فيك العميل؟ - قدم مشوارك في هذا المجال الذي تحترفه والنتائج التي تحصلت عليها. - استعرض المشكل الذي يتعرض له الزائر وكيف أنك يمكنك أن تقدم لهم الحل. - حفّز الزائر والعميل، حرك مشاعره بأنه في حال حصوله على المنتج سيجد الحل وأهم الفوائد التي سيتحصل عليها فور ذلك. - استعرض نتائج كل من جرّب المنتج أو الخدمة. - ضع الشهادات والتقييمات الإيجابية لمختلف عملاءك. - في الأخير ضع ثمن المنتج. - ضع حق ضمان بإرجاع الأموال في حال عدم الإعجاب بالمنتج. - ضمان خدمة ما وراء البيع. فهذه المكونات كلها يجب أن تكون في صفحة البيع، حضورها سيزيد من مصداقيتك وبالتالي في نسبة التحويل.1 نقطة
-
تشرف سنة 2015 على نهايتها، وفي هذا الإطار أريد الاستفسار عن جديد الويب ماركتينج هذه السنة، ماهي الطرق الجديدة الناجحة في هذا المجال؟ وخاصة ماهي أهم التقنيات التي يمكن بدء سنة 2016 بها؟1 نقطة
-
هذا صحيح، أشكرك لقد ساعدتني وتم حل المشكلة. ظلال الشمس كانت بقيمة 20cm وعند تخفيفها لغاية 2cm نجح الأمر واختفى التوهج. شكرًا لك.1 نقطة
-
لهذا ظهر شكل الخلفية مشوّهًا حيث أن الرندر للأشكال من هذا النوع مع اعتماد التنعيم تسبب عدم التجانس ما يشوّه الألوان والانعكاس . لذلك من الأفضل أن تعيد النظر في الدرس الذي تتابعه لعلك فوّت خطوة . أو بإمكانك قطع السطح المنحرف عند نهاية هذا الانحراف وبداية السطح الأفقي ثم إنشاء شكل أفقي منفصل ملاصق ومكمّل للسطح المنحرف ويمكنك استخدام ميزة Connect لوصلها فيما بعد حيث ستتجنب أية أخطاء قد تحصل في نتائج الرندر.1 نقطة