لا يمكن لعناصر اللوحة الداخلية إضافة مستمعي الأحداث التفاعلية بشكل ملائم مثل عناصر DOM، لأنه لا يوجد مفهوم للعناصر في لوحة الرسم، فهي مجرد رسومات مرسومة بواسطة لوحة الرسم. هذه عقبة ضرورية للتطوير التفاعلي. فكرة مراقبة حدث النقر للرسم بسيطة للغاية. ما عليك سوى الاستماع إلى حدث النقر لعنصر اللوحة القماشية نفسه، ثم تحديد الرسم الذي توجد إحداثيات النقر بداخله ومن ثم يمكن تحقيق حدث النقر الرسومي بشكل مقنع. ستقدم هذه المقالة ثلاث طرق لتحديد ما إذا كانت النقطة الإحداثية موجودة داخل رسم قماشي أم لا.
اتفاقالطرق الثلاثة المقدمة في هذه المقالة مناسبة لتحديد أحداث النقر الرسومية ذات الأشكال غير المنتظمة والمواضع غير المنتظمة في اللوحة القماشية، بالنسبة للمشاهد ذات الأشكال المنتظمة أو المواضع المنتظمة، يجب أن تكون هناك تطبيقات أبسط، وهو ما لن يتم مناقشته هنا.
طريقة البكسلتتمثل فكرة طريقة اكتشاف البكسل في رسم رسومات متعددة في اللوحة القماشية (إذا كانت متعددة) خارج الشاشة بشكل منفصل، واستخدام طريقة getImageData () للحصول على بيانات البكسل وحفظها. عندما يستمع عنصر اللوحة إلى حدث النقر، يمكن استخدام إحداثيات النقر لحساب البكسل مباشرة على اللوحة التي حدثت فيها النقرة، ثم اجتياز بيانات الرسومات المحفوظة مسبقًا لمعرفة ما إذا كانت قيمة ألفا لهذا البكسل هي 0. إذا فهو 0، فهذا يعني أن نقطة الهبوط ليست ضمن الشكل الحالي، وإلا فهذا يعني أن النقطة قد وصلت إلى هذا الرقم.
طريقة الحصول على رقم البكسل الذي تم النقر عليه بناءً على إحداثيات النقر:
رقم البكسل = (الإحداثي-1) * عرض اللوحة القماشية + الإحداثي الإحداثي
على سبيل المثال، إذا قمت بالنقر فوق الإحداثيات (3،3) على لوحة بعرض 5، فإن رقم البكسل الذي تم الحصول عليه وفقًا للصيغة أعلاه هو (3-1) * 5 + 3 = 18، كما هو موضح في الشكل:
نظرًا لأن البيانات الرسومية المصدرة بواسطة اللوحة القماشية تخزن كل بكسل في مصفوفة مكونة من 4 أرقام بترتيب rgba، لذلك إذا كنت تريد الوصول إلى قيمة ألفا لبكسل محدد، فأنت تحتاج فقط إلى قراءة قيمة pIndex * 4 + 3 لهذه المصفوفة. ، إذا لم تكن هذه القيمة 0، فهذا يعني أن البكسل مرئي، أي أنه تم النقر على الرسم.
هذه الطريقة هي التي أعتقد أنها تحتوي على الأفكار الأكثر مباشرة والنتائج الأكثر دقة، وليس لها أي متطلبات على شكل الرسومات، ومع ذلك، فإن هذه الطريقة لها قيود قاتلة عندما يلزم نقل الرسومات على القماش ، يجب إنشاء ذاكرة التخزين المؤقت للبيانات بشكل متكرر لضمان دقة النتائج، حيث يتأثر أداء طريقة getImageData () بحجم اللوحة القماشية وعدد الرسومات. لذا، إذا كانت لوحة الرسم القماشية ثابتة، فهذه الطريقة مناسبة جدًا، وإلا فلن تكون مناسبة لاستخدام هذه الطريقة.
طريقة الزاويةمن السهل فهم مبدأ طريقة الحكم على الزوايا، إذا كانت هناك نقطة داخل مضلع، فيجب أن يصل مجموع الزاوية بين النقطة وجميع رؤوس المضلع إلى 360 درجة بالضبط.
يمكن تحويل عملية الحساب إلى الخطوات الثلاث التالية:
1. بالنظر إلى رؤوس المضلعات المعروفة والإحداثيات المعروفة، قم بدمج الإحداثيات والرؤوس في أزواج لتكوين قائمة انتظار من ثلاث نقاط.
2. للعثور على الزاوية بين ثلاث نقاط معروفة، يمكنك استخدام نظرية يو شوان
3. تحديد ما إذا كان مجموع الزوايا المضمنة هو 360 درجة
كل خطوة بسيطة ويتم تنفيذها على النحو التالي:
// احسب المسافة بين نقطتين const getDistence = function (p1, p2) { return Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.x). y) * (p1.y - p2.y))};// تحدد طريقة الزاوية أن النقطة موجودة داخل المضلع const checkPointInPolyline = (point, polylinePoints) => { Let TotalA = 0; const A = point; for (let i = 0; i < polylinePoints.length; i++) { Let B, C; if (i === polylinePoints.length - 1) { B = { x: polylinePoints[i][0] ], y: polylinePoints[i][1] }; C = { x: polylinePoints[0][0], y: polylinePoints[0][1] }; else { B = { x: polylinePoints[i][0], y: polylinePoints[i][1] }; } // احسب الزاوية const angleA = Math.acos((Math.pow(getDistence(A, C), 2) + Math.pow(getDistence(A, B), 2) - Math.pow(getDistence(B, C), 2)) / (2 * getDistence(A, C) * getDistence(A, B))) TotalA += angleA } // الحكم على مجموع ترجع الزوايا TotalA === 2 * Math.PI}أحد قيود هذه الطريقة هو أن الشكل يجب أن يكون مضلعًا محدبًا. إذا لم يكن المضلع مضلعًا محدبًا، فيجب تقطيعه إلى مضلع محدب قبل الحساب، وهو أمر أكثر تعقيدًا.
فكرة مماثلة هي طريقة المساحة. إذا كانت هناك نقطة داخل مضلع، فإن مجموع مساحات المثلث الذي تشكله النقطة وجميع رؤوس المضلع يجب أن يكون مساوياً لمساحة المضلع من الصعب جدًا حساب مساحة المضلع أولاً، لذا فهذه الطريقة يمكنك تمريرها مباشرة.
طريقة رايطريقة الشعاع هي طريقة لا أستطيع شرحها بشكل واضح ولكنها سهلة الاستخدام للغاية، طالما أن عدد نقاط التقاطع بين نقطة وجانب واحد من المضلع هو رقم فردي، فإن النقطة موجودة داخل المضلع. لاحظ أنك تحتاج فقط إلى حساب عدد نقاط التركيز على أي جانب، مثل الجانب الأيسر. هذه الطريقة لا تحدد نوع المضلع، فالمضلعات المحدبة أو المضلعات المقعرة أو حتى الحلقات مقبولة.
كما أنه سهل التنفيذ للغاية:
const checkPointInPolyline = (point, polylinePoints) => { // طريقة الشعاع Let leftSide = 0; const A = point; for (let i = 0; i < polylinePoints.length; i++) { Let B, C; == polylinePoints.length - 1) { B = { x: polylinePoints[i][0], y: polylinePoints[i][1] }; polylinePoints[0][0], y: polylinePoints[0][1] } else { B = { x: polylinePoints[i][0], y: polylinePoints[i][1] }; : polylinePoints[i + 1][0], y: polylinePoints[i + 1][1] }; // القاضي بالتقاطع الأيسر Let SortByY = [By, Cy].sort((a,b) => ab) if (sortByY[0] < Ay &&sortByY[1] > Ay){ if(Bx<Ax || Cx < Ax){ leftSide++ } } } return leftSide % 2 === 1}هناك حالة خاصة من طريقة الشعاع، والتي تتطلب معالجة خاصة عندما تكون النقطة على حافة التشوهات المتعددة. لكن في الهندسة، أعتقد أنه لا يحتاج إلى معالجة، لأنه إذا نقر المستخدم على حدود الرسم، فإن البرنامج يعتقد أنه لم ينقر ويمكنه المرور.
تلخيصيمكن للطرق الثلاث المذكورة أعلاه تحقيق اكتشاف النقرات للرسومات غير المنتظمة في اللوحة القماشية. من بينها، ميزة طريقة البكسل هي أنها لا تختار الأشكال ولها مزايا أداء معينة في المشاهد الثابتة؛ يجب أن يقال أن طريقة الزاوية لها قيمة نظرية فقط وعملية ضعيفة، والأكثر عملية في الهندسة هي طريقة الشعاع ، والتي لها قيود قليلة وسهلة التنفيذ، وفي معظم الأحيان تحتاج فقط إلى معرفة طريقة الشعاع.