English | 简体中文 | 繁體中文 | Русский язык | Français | Español | Português | Deutsch | 日本語 | 한국어 | Italiano | بالعربية
المقدمة
ظهور RequireJS جعل تمايز الكود الأمامي أسهل، وعندما يصبح مشروعك الأمامي أكبر وكوده أكثر، فإن التمايز يجعل بنية المشروع أكثر وضوحًا، ليس فقط يجعل أفكارنا أكثر وضوحًا أثناء التطوير، بل يجعل الصيانة أيضًا أسهل. إليك برنامج الرسم التخطيطي البسيط الذي قمت بتطويره باستخدام RequireJS بعد دراستي له، ويتم تشغيله في المتصفح كما هو موضح في الشكل التالي:
إذا لم تكن تعرف RequireJS بعد، يمكنك قراءة ملاحظات دراستي لـ RequireJS:http://blog.csdn.net/yubo_725/article/details/52913853
البداية
هذا البرنامج البسيط للرسم التخطيطي يعرض بنية المشروع كما هو موضح في الشكل التالي:
يُعتبر index.html هو صفحة المشاريع،يُوضع جميع ملفات js في مجلد js،مجلد js/app يحتوي على ملفات النصوص النمطية الخاصة بنا،مجلد js/lib لا يحتوي على ملفات حاليًا،عندما يستخدم مشروعنا بعض الأطر الأمامية مثل jquery،سيُوضع هذه الأطر في مجلد js/lib،ملف js/main.js هو ملف تكوين requirejs،يعني تكوين بعض المسارات،ملف js/require.min.js هو ملف نمط RequireJS. يرجى اتباعى الخطوات التالية لإنشاء برنامج الرسم البسيط هذا خطوة بخطوة!]}
الجزء الأول: تكوين requirejs
يتم وضع ملف تكوين المشروع في js/main.js،الكود التالي هو:
require.config({ baseUrl: 'js/lib', paths: { app: '../app' } )
يتم تكوينه بشكل رئيسي لجعل مسار الجذر لمشروع 'js/lib'،ثم تكوين مسار يُدعى 'app'، المسار هو '../app'، أي مسار 'js/app'.
الجزء الثاني: كتابة النصوص النمطية
يوجد عدة نماذج في هذا المشروع كالتالي: نمط النصوص.js, خط النصوص.js, مربع.js, دائرة.js, utils.js،وسأوضحها لاحقًا:
نمط النصوص.js:
نمط النصوص.js يمثل نقطة (x, y)، الكود التالي هو:
/** نقطة */ define(function() { return function(x, y) { this.x = x; this.y = y; this.equals = function(point) { return this.x === point.x && this.y === point.y; }; }; )
استخدم الكود المذكور أعلاه define لتحديد نمط النقطة، يعني فئة في func callback، تحتوي على اثنين من المعلمات x،y،و يوجد method equals للتحقق من إسقاطين إذا كانا متساويين.
للإستخدام هذا النمط، يمكن استخدام الكود التالي:
require(['app/point'], function(Point) { // إنشاء نموذج فئة النقطة var point = new Point(3, 5); )
يحتاج الانتباه إلى أن أول متغير في func require() هو مجموعة، يعني Point في func callback يمثل فئة النقطة، يتم إنشاء نموذج فئة النقطة باستخدام new Point().
خط النصوص.js:
خط النصوص.js يمثل خط مستقيم، الكود التالي هو:
/** خط مستقيم */ define(function() { return function(startPoint, endPoint) { this.startPoint = startPoint; this.endPoint = endPoint; this.drawMe = function(context) { context.strokeStyle = "#000000"; context.beginPath(); context.moveTo(this.startPoint.x, this.startPoint.y); context.lineTo(this.endPoint.x, this.endPoint.y); context.closePath(); context.stroke(); } } )
تعريف مودل الخط يتشابه مع تعريف مودل النقطة، حيث يتم إرجاع فئة في دالة callback من define، ويتضمن بناء الخط فئة نقطة كمرجعين، يمثلان البداية والنهاية للخط، ويوجد أيضًا طريقة drawMe لرسم الخط من خلال إدخال مجال السياق.
rect.js:
مودل rect.js يمثل مستطيل، والكود كالتالي:
/** مستطيل */ define(['app/point'], function() { return function(startPoint, width, height) { this.startPoint = startPoint; this.width = width; this.height = height; this.drawMe = function(context) { context.strokeStyle = "#000000"; context.strokeRect(this.startPoint.x, this.startPoint.y, this.width, this.height); } } )
حيث startPoint هو موضع الزاوية العلوية اليسرى للمستطيل، وهو من فئة point، وwidth وheight يمثلان عرض وارتفاع المستطيل على التوالي، ويوجد أيضًا طريقة drawMe لرسم المستطيل نفسه.
arc.js:
مودل arc.js يمثل دائرة، والكود كالتالي:
/** دائرة */ define(function() { return function(startPoint, radius) { this.startPoint = startPoint; this.radius = radius; this.drawMe = function(context) { context.beginPath(); context.arc(this.startPoint.x, this.startPoint.y, this.radius, 0, 2 * Math.PI); context.closePath(); context.stroke(); } } )
حيث يعني startPoint موضع الزاوية العلوية اليسرى للمستطيل الذي يحتوي على الدائرة، ويشير radius إلى نصف قطر الدائرة، وهو يوجد طريقة drawMe لرسم الدائرة.
تتضمن جميع الوحدات المذكورة أعلاه كائنات خط مستقيم ومستطيل ودائرة تحتوي على طريقة drawMe()، ويتم هنا استخدام معرفة رسم الـ canvas، إذا لم تكن متأكدًا من شيء، يمكنك الرجوع إلى دليل HTML 5 Canvas.
utils.js
مодуل utils.js يستخدم لمعالجة أدوات رسم مختلفة، بما في ذلك رسم الخطوط والمستطيلات والدوائر، بالإضافة إلى تسجيل مسارات الرسم وازالة مسارات الرسم، والكود كالتالي:
/** أدوات إدارة الرسم */ define(function() { var history = []; //يستخدم هذا المفتاح لتخزين سجلات الرسم التاريخية، ويحتوي على كائنات خط مستقيم أو مستطيل أو دائرة function drawLine(context, line) { line.drawMe(context); } function drawRect(context, rect) { rect.drawMe(context); } function drawArc(context, arc) { arc.drawMe(context); } /** إضافة مسار رسمي جديد */ function addHistory(item) { history.push(item); } /** رسم المسار التاريخي */ function drawHistory(context) { for(var i = 0; i < history.length; i++) { var obj = history[i]; obj.drawMe(context); } } /** حذف المسار التاريخي */ function clearHistory() { history = []; } return { drawLine: drawLine, drawRect: drawRect, drawArc: drawArc, addHistory: addHistory, drawHistory: drawHistory, clearHistory: clearHistory }; )
ثالثًا، كتابة كود واجهة المستخدم، معالجة أحداث الفأرة
لقد تم بالفعل تعريف جميع الوحدات البرمجية للبرنامج البسيط للرسم في هذه المرة، والوحدات التي يتم استخدامها في رسم الشكل هي الوحدات القليلة التي ذكرت أعلاه، وستبدأ الآن في كتابة كود واجهة المستخدم الرئيسية، تحتوي واجهة المستخدم الرئيسية على أربعة أزرار، بالإضافة إلى لوحة رسم كبيرة تستخدم للرسم، إليك كود ملف index.html مباشرةً:
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>برنامج رسم بسيط</title> <style type="text/css"> canvas { background-color: #ECECEC; cursor: default; /** إعداد الماوس إلى المؤشر الافتراضي */ } .tool-bar { margin-bottom: 10px; } </style> </head> <body> <div class="tool-bar"> <button id="btn-line">رسم خط مستقيم</button> <button id="btn-rect">رسم مستطيل</button> <button id="btn-oval">رسم دائرة</button> <button id="btn-clear">إزالة كل شيء من لوحة الرسم</button> <span id="hint" style="color: red;">العمل الحالي: رسم الخط المستقيم</span> </div> <canvas id="canvas" width="800" height="600"></canvas> <script type="text/javascript" src="js/require.min.js" data-main="js/main"></script> <script type="text/javascript"> require(['app/point', 'app/line', 'app/rect', 'app/arc', 'app/utils'], function(Point, Line, Rect, Arc, Utils) { var canvas = document.getElementById("canvas"); var context = canvas.getContext('2d'); var canvasRect = canvas.getBoundingClientRect(); // الحصول على المربع الذي يحتوي على canvas canvas.addEventListener('mousedown', handleMouseDown); canvas.addEventListener('mousemove', handleMouseMove); canvas.addEventListener('mouseup', handleMouseUp); bindClick('btn-clear', menuBtnClicked); bindClick('btn-line', menuBtnClicked); bindClick('btn-rect', menuBtnClicked); bindClick('btn-oval', menuBtnClicked); var mouseDown = false; var selection = 1; // 0, 1, 2 تمثل رسم الخط، رسم المربع، رسم الدائرة var downPoint = new Point(0, 0), movePoint = new Point(0, 0), upPoint = new Point(0, 0); var line; var rect; var arc; /** معالجة حدث الضغط على الفأرة */ function handleMouseDown(event) { downPoint.x = event.clientX - canvasRect.left; downPoint.y = event.clientY - canvasRect.top; if(selection === 0) { line = new Line(downPoint, downPoint); line.startPoint = downPoint; } else if(selection === 1) { rect = new Rect(new Point(downPoint.x, downPoint.y), 0, 0); } else if(selection === 2) { arc = new Arc(new Point(downPoint.x, downPoint.y), 0); } mouseDown = true; } /** معالجة حادثة تحريك الماوس */ function handleMouseMove(event) { movePoint.x = event.clientX - canvasRect.left; movePoint.y = event.clientY - canvasRect.top; إذا (movePoint.x == downPoint.x && movePoint.y == downPoint.y) { return ; } إذا (movePoint.x == upPoint.x && movePoint.y == upPoint.y) { return ; } إذا (mouseDown) { clearCanvas(); إذا (selection == 0) { line.endPoint = movePoint; Utils.drawLine(context, line); } rect.width = movePoint.x - downPoint.x; rect.height = movePoint.y - downPoint.y; Utils.drawRect(context, rect); } آخره إذا كان selection == 2) { var x = movePoint.x - downPoint.x; var y = movePoint.y - downPoint.y; arc.radius = x > y ? (y / 2) : (x / 2); إذا (arc.radius < 0) { arc.radius = -arc.radius; } arc.startPoint.x = downPoint.x + arc.radius; arc.startPoint.y = downPoint.y + arc.radius; Utils.drawArc(context, arc); } Utils.drawHistory(context); } } /** معالجة حادثة رفع الماوس */ function handleMouseUp(event) { upPoint.x = event.clientX - canvasRect.left; upPoint.y = event.clientY - canvasRect.top; إذا (mouseDown) { mouseDown = false; إذا (selection == 0) { line.endPoint = upPoint; إذا (!downPoint.equals(upPoint)) { Utils.addHistory(new Line(new Point(downPoint.x, downPoint.y), new Point(upPoint.x, upPoint.y))); } } rect.width = upPoint.x - downPoint.x; rect.height = upPoint.y - downPoint.y; Utils.addHistory(new Rect(new Point(downPoint.x, downPoint.y), rect.width, rect.height)); } آخره إذا كان selection == 2) { Utils.addHistory(new Arc(new Point(arc.startPoint.x, arc.startPoint.y), arc.radius)); } clearCanvas(); Utils.drawHistory(context); } } /** تنظيف اللوحة الرسمية */ function clearCanvas() { context.clearRect(0, 0, canvas.width, canvas.height); } /** معالجة أحداث الضغط على زر القائمة */ function menuBtnClicked(event) { var domID = event.srcElement.id; if(domID === 'btn-clear') { clearCanvas(); Utils.clearHistory(); } selection = 0; showHint('العمل الحالي: رسم خط'); } selection = 1; showHint('العمل الحالي: رسم مستطيل'); } آخره إذا كان domID == 'btn-oval' { selection = 2; showHint('العمل الحالي: رسم دائرة'); } } function showHint(msg) { document.getElementById('hint').innerHTML = msg; } /** لربط أحداث النقر للعنصر DOM المحدد */ function bindClick(domID, handler) { document.getElementById(domID).addEventListener('click', handler); } }); </script> </body> </html>
يوجد الكثير من الكود في ملف index.html، ولكن الكود الرئيسي هو الاستماع والمعالجة لثلاثة أحداث: النقر، الحركة، والرفع، بالإضافة إلى ذلك، يجب الانتباه عند الحصول على موقع الماوس في الكناس، لأن clientX وclientY في object event هي موقع الماوس بالنسبة للصفحة، لتحديد موقع الماوس في الكناس، يجب الحصول على منطقة المربع الخاصة بالكناس، ثم يمكن الحصول على موقع الماوس في الكناس باستخدام clientX-canvas.left، clientY-canvas.top
مصدر الكود
تم توفير كود هذا المقال على github، انقر هنا لمعاينةمصدر الكود
bug معروف
عند رسم دائرة يجب أن يتم سحب الماوس من الزاوية العلوية اليسرى إلى الزاوية السفلية اليمنى لرسم الدائرة، وإذا لم يكن ذلك، قد تكون هناك مشكلة في موقع الدائرة.
هذا هو نهاية محتويات هذا المقال، نأمل أن تكون قد ساعدت في تعلم الجميع، ونأمل أن تحصلوا على دعمكم الكبير لتدريب النفخ.
بيان: محتويات هذا المقال تم جمعها من الإنترنت، ملكية المحتويات للملكين الأصليين، تم جمع المحتويات من قبل المستخدمين عبر الإنترنت بطرقهم الخاصة، ويتمتع هذا الموقع بلا حقوق ملكية، ويتمتع المحتوى بمعالجة يدوية، ولا يتحمل الموقع أي مسؤولية قانونية. إذا وجدت محتوى يشتبه في حقوق النسخ، فلا تتردد في إرسال بريد إلكتروني إلى: notice#oldtoolbag.com (عند إرسال البريد الإلكتروني، يرجى استبدال # ب @) للإبلاغ، وتقديم الدليل ذات صلة، وإذا تم التحقق من ذلك، سيتم حذف المحتوى المشبوه فوراً.