it-swarm.asia

كيف أضيف معالج حدث onClick بسيط إلى عنصر قماش؟

أنا مبرمج جافا ذي خبرة ولكنني أنظر إلى بعض عناصر JavaScript/HTML5 لأول مرة منذ حوالي عقد. أنا متعثر تمامًا على ما ينبغي أن يكون أبسط شيء على الإطلاق.

كمثال ، أردت فقط رسم شيء وإضافة معالج حدث إليه. أنا متأكد من أنني أقوم بشيء غبي ، لكنني بحثت في كل شيء ولم أقترح أي شيء (على سبيل المثال ، الإجابة على هذا السؤال: أضف خاصية onclick لإدخالها في JavaScript ). أنا أستخدم Firefox 10.0.1. يتبع الكود الخاص بي. سترى العديد من الأسطر المعلقة وفي نهاية كل منها وصف لما يحدث (أو ما لا يحدث).

ما هو بناء الجملة الصحيح هنا؟ سيصيبني الجنون!

<html>
<body>
    <canvas id="myCanvas" width="300" height="150"/>
    <script language="JavaScript">
        var elem = document.getElementById('myCanvas');
        // elem.onClick = alert("hello world");  - displays alert without clicking
        // elem.onClick = alert('hello world');  - displays alert without clicking
        // elem.onClick = "alert('hello world!')";  - does nothing, even with clicking
        // elem.onClick = function() { alert('hello world!'); };  - does nothing
        // elem.onClick = function() { alert("hello world!"); };  - does nothing
        var context = elem.getContext('2d');
        context.fillStyle = '#05EFFF';
        context.fillRect(0, 0, 150, 100);
    </script>

</body>
108
Jer

عندما تقوم بالرسم إلى عنصر canvas ، فأنت ببساطة ترسم صورة نقطية في الوضع الفوري .

العناصر (الأشكال والخطوط والصور) التي يتم رسمها ليس لها تمثيل بجانب البيكسلات التي تستخدمها ولونها.

لذلك ، للحصول على حدث انقر على canvaselement (الشكل) ، تحتاج إلى التقاط أحداث النقر على عنصر HTML _canvas واستخدام بعض الرياضيات لتحديد العنصر الذي تم النقر فوقه ، بشرط أنت تقوم بتخزين عرض/ارتفاع العناصر وإزاحة x/y.

لإضافة حدث click إلى عنصر canvas الخاص بك ، استخدم ...

canvas.addEventListener('click', function() { }, false);

لتحديد ما تم النقر على {element ...

var elem = document.getElementById('myCanvas'),
    elemLeft = elem.offsetLeft,
    elemTop = elem.offsetTop,
    context = elem.getContext('2d'),
    elements = [];

// Add event listener for `click` events.
elem.addEventListener('click', function(event) {
    var x = event.pageX - elemLeft,
        y = event.pageY - elemTop;

    // Collision detection between clicked offset and element.
    elements.forEach(function(element) {
        if (y > element.top && y < element.top + element.height 
            && x > element.left && x < element.left + element.width) {
            alert('clicked an element');
        }
    });

}, false);

// Add element.
elements.Push({
    colour: '#05EFFF',
    width: 150,
    height: 100,
    top: 20,
    left: 15
});

// Render elements.
elements.forEach(function(element) {
    context.fillStyle = element.colour;
    context.fillRect(element.left, element.top, element.width, element.height);
});​

jsFiddle .

يقوم هذا الرمز بإرفاق حدث click بالعنصر canvas ، ثم يدفع شكلًا واحدًا (يسمى element في الكود الخاص بي) إلى صفيف elements. يمكنك إضافة ما تريد هنا.

الغرض من إنشاء مجموعة من الكائنات هو أنه يمكننا الاستعلام عن خصائصها لاحقًا. بعد أن يتم دفع جميع العناصر إلى المصفوفة ، فإننا ندخل ونعرض كل عنصر بناءً على خصائصه.

عندما يتم تشغيل الحدث click ، فإن الكود ينطلق خلال العناصر ويحدد ما إذا كانت النقرة قد تجاوزت أي من العناصر الموجودة في المصفوفة elements. إذا كان الأمر كذلك ، فإنه يطلق وظيفة alert() ، والتي يمكن تعديلها بسهولة للقيام بشيء مثل إزالة عنصر الصفيف ، وفي هذه الحالة ستحتاج إلى وظيفة render منفصلة لتحديث canvas.

للاكتمال ، لماذا لم تنجح محاولاتك ...

elem.onClick = alert("hello world"); // displays alert without clicking

هذا هو تعيين قيمة الإرجاع لـ alert() إلى الخاصية onClickelem. يتم استدعاء على الفور alert().

elem.onClick = alert('hello world');  // displays alert without clicking

في JavaScript ، يكون ' و " متطابقين بشكل شبه منطقي ، وربما يستخدم lexer ['"] لعروض الأسعار.

elem.onClick = "alert('hello world!')"; // does nothing, even with clicking

أنت تقوم بتعيين سلسلة لخاصية onClickelem.

elem.onClick = function() { alert('hello world!'); }; // does nothing

جافا سكريبت حساس لحالة الأحرف. الخاصية onclick هي الطريقة القديمة لإرفاق معالجات الأحداث. يسمح فقط بربط حدث واحد بالخاصية ويمكن فقدان الحدث عند إجراء تسلسل HTML.

elem.onClick = function() { alert("hello world!"); }; // does nothing

مرة أخرى ، ' === ".

183
alex

أوصي بالمقال التالي: Hit Detection Detection لـ HTML5 Canvas و How To To Click To Click Events on Canvas Shapes الذي يمر بمختلف المواقف.

ومع ذلك ، فإنه لا يغطي addHitRegion API ، والتي يجب أن تكون أفضل طريقة (استخدام وظائف الرياضيات و/أو المقارنات عرضة للخطأ تمامًا). هذا النهج مفصل على developer.mozilla

3
RUser4512

ربما فات الأوان على الإجابة لكنني فقط قرأت هذا أثناء التحضير لامتحان 70-480 الخاص بي ، ووجدت أنه يعمل -

var elem = document.getElementById('myCanvas');
elem.onclick = function() { alert("hello world"); }

لاحظ الحدث كـ onclick بدلاً من onClick.

JS Bin مثال.

2
Soham Dasgupta

يمكنك أيضًا وضع عناصر DOM ، مثل div أعلى اللوحة التي تمثل عناصر قماشك وسيتم وضعها بنفس الطريقة.

يمكنك الآن إرفاق مستمعي الأحداث بهذه divs وتنفيذ الإجراءات اللازمة.

1
Sergei Basharov

كبديل لإجابة أليكس:

يمكنك استخدام رسم SVG بدلاً من رسم Canvas. هناك يمكنك إضافة الأحداث مباشرة إلى كائنات DOM المرسومة.

انظر على سبيل المثال:

جعل كائن صورة svg قابل للنقر مع onclick ، ​​وتجنب تحديد الموقع المطلق

1
Goswin

كبديل رخيص آخر على قماش ثابت إلى حد ما ، استخدام عنصر img تراكب مع تعريف خريطة الموقع سريعة وقذرة. يعمل بشكل جيد بشكل خاص على عناصر قماشية قائمة على المضلع مثل مخطط دائري.

0
TadLewis

Alex Answer جميل جداً ولكن عند استخدام تدوير السياق ، قد يكون من الصعب تتبع إحداثيات x ، y ، لذلك قمت بإجراء Demo توضح كيفية تتبع ذلك.

أنا في الأساس أستخدم هذه الوظيفة وأعطيها الزاوية وكمية المسافة المقطوعة في ذلك الملاك قبل رسم الكائن.

function rotCor(angle, length){
    var cos = Math.cos(angle);
    var sin = Math.sin(angle);

    var newx = length*cos;
    var newy = length*sin;

    return {
        x : newx,
        y : newy
    };
}
0
Imran Bughio