मैं एक कैनवस तत्व पर एक साधारण ऑनक्लिक इवेंट हैंडलर कैसे जोड़ूं?


128

मैं एक अनुभवी जावा प्रोग्रामर हूं, लेकिन लगभग एक दशक में पहली बार कुछ जावास्क्रिप्ट / एचटीएमएल 5 सामान देख रहा हूं। मैं पूरी तरह से इस बात पर अडिग हूं कि अब तक की सबसे सरल चीज क्या होनी चाहिए।

एक उदाहरण के रूप में मैं बस कुछ आकर्षित करना चाहता था और इसमें एक इवेंट हैंडलर जोड़ना चाहता था। मुझे यकीन है कि मैं कुछ बेवकूफी कर रहा हूं, लेकिन मैंने सभी को खोजा है और कुछ भी नहीं सुझाया गया है (उदाहरण के लिए इस सवाल का जवाब: जावास्क्रिप्ट पर इनपुट के साथ onclick संपत्ति जोड़ें ) काम करता है। मैं फ़ायरफ़ॉक्स 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>


8
के onclickबजाय का उपयोग करेंonClick
noob

1
यह बताने के लिए कि उन प्रयासों ने काम क्यों नहीं किया ... टिप्पणियों के पहले जोड़े तुरंत एक चेतावनी प्रदर्शित करते हैं क्योंकि आप एक फ़ंक्शन को परिभाषित करने के बजाय alert()सीधे कॉल कर रहे हैं <script>जो कॉल करेगा alert()। के पूंजीकरण के कारण बाकी कुछ नहीं करते हैं onclick
लार्स

आप इस lib jsfiddle.net/user/zlatnaspirala/fiddles का उपयोग कर सकते हैं , bitbucket.org/nikola_l/visual-js पर दिखता है । आपको बहुत सारे फीचर्स मिलेंगे +
Nikola Lukic

जवाबों:


223

जब आप किसी canvasतत्व को आकर्षित करते हैं, तो आप बस तत्काल मोड में एक बिटमैप खींच रहे हैं ।

तत्वों (आकृतियों, रेखाओं, चित्रों) को खींचा जाता है उनका उपयोग करने वाले पिक्सेल और उनके रंग के अलावा कोई प्रतिनिधित्व नहीं होता है।

इसलिए, किसी तत्व (आकृति) पर एक क्लिक ईवेंट प्राप्त करने के लिए , आपको क्लिक इवेंट को कैप्चर करना होगाcanvas canvas HTML तत्व और यह निर्धारित करने के लिए कुछ गणित का उपयोग करना होगा कि किस तत्व को क्लिक किया गया था, बशर्ते आप तत्वों की चौड़ाई / ऊँचाई और x / y ऑफसेट संग्रहीत कर रहे हों ।

clickअपने canvasतत्व में कोई ईवेंट जोड़ने के लिए , उपयोग करें ...

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

यह निर्धारित करने के लिए कि किस तत्व पर क्लिक किया गया ...

var elem = document.getElementById('myCanvas'),
    elemLeft = elem.offsetLeft + elem.clientLeft,
    elemTop = elem.offsetTop + elem.clientTop,
    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(), जिसे आसानी से संशोधित करने के लिए कुछ किया जा सकता है जैसे कि सरणी आइटम को हटा दें, जिस स्थिति में आपको अपडेट करने के लिए एक अलग रेंडर फ़ंक्शन की आवश्यकता होगी canvas


पूर्णता के लिए, आपके प्रयासों ने काम क्यों नहीं किया ...

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

यह alert()की onClickसंपत्ति का रिटर्न मान निर्दिष्ट कर रहा है elem। यह तुरंत आह्वान कर रहा है alert()

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

जावास्क्रिप्ट में, 'और "शब्दार्थ समान हैं, लेक्सर शायद ['"]उद्धरण के लिए उपयोग करता है।

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

आप की onClickसंपत्ति के लिए एक स्ट्रिंग प्रदान कर रहे हैं elem

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

जावास्क्रिप्ट संवेदनशील है। onclickसंपत्ति ईवेंट हैंडलर्स संलग्न के पुरातन पद्धति है। यह केवल एक घटना को संपत्ति के साथ संलग्न करने की अनुमति देता है और HTML को क्रमबद्ध करने पर घटना खो सकती है।

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

फिर, ' === "


हम्म ... मुझे माफ कर दो अगर मैं गलत समझ रहा हूँ - लेकिन क्या मैं कैनवास तत्व पर क्लिक की घटनाओं को कैप्चर नहीं कर रहा हूँ? मुझे यकीन नहीं है कि आप किस तत्व से मतलब रखते हैं । इस पृष्ठ पर केवल एक ही तत्व है, है ना?
जेर

उनका मतलब था "कैनवास के भीतर कौन सा तत्व" - ऐसा कहने के लिए "आकार" है।
जोवन पेरोविक

1
धन्यवाद, बहुत बहुत - हालांकि मैं पिछले एक पर पूरी तरह से स्पष्ट नहीं हूं। मैं यहां उदाहरण का अनुसरण कर रहा हूं: developer.mozilla.org/en/DOM/element.onclick (अनाम फ़ंक्शन का वर्णन करते हुए उपयोग करते हुए) और यह तब भी काम करता है, जब मैं एक कैनवास पर स्पैन बदलता हूं। इसलिए मेरे लिए यह मुश्किल नहीं होगा कि मैं उनका उदाहरण धीरे-धीरे बदल दूं कि मैं क्या कर रहा हूं। विस्तृत प्रतिक्रिया के लिए धन्यवाद! मेरे विभिन्न प्रयासों के गलत होने की व्याख्या विशेष रूप से सहायक थी।
जेर

1
@ जेर कोई चिंता नहीं, अगर आपके पास और प्रश्न हैं, तो बेझिझक मुझे ट्विटर पर पोस्ट करें और पिंग करें, @alexdickson
एलेक्स

1
@HashRocketSyntax यह ठीक काम करना चाहिए, बस अपनी वस्तुओं की स्थिति को स्मृति में अपडेट करें और रेंडर करने के लिए उन परिभाषाओं का उपयोग करें
एलेक्स

4

शायद उत्तर देने में बहुत देर हो गई लेकिन मैंने अपनी 70-480परीक्षा की तैयारी के दौरान सिर्फ यह पढ़ा , और यह काम करने के लिए पाया -

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

ईवेंट को onclickइसके बजाय नोटिस करें onClick

जेएस बिन उदाहरण।


3

मैं निम्नलिखित लेख की सिफारिश करता हूं: एचटीएमएल 5 कैनवस के लिए हिट रीजन डिटेक्शन और कैनवस शेप पर ईवेंट पर क्लिक करने के लिए कैसे सुनना है जो विभिन्न स्थितियों में जाता है।

हालांकि, यह addHitRegionएपीआई को कवर नहीं करता है, जो सबसे अच्छा तरीका होना चाहिए (गणित कार्यों और / या तुलना का उपयोग करना काफी त्रुटि प्रवण है)। यह दृष्टिकोण developer.mozilla पर विस्तृत है


"[ addHitRegion] अप्रचलित है। हालांकि यह अभी भी कुछ ब्राउज़रों में काम कर सकता है, इसका उपयोग हतोत्साहित किया जाता है क्योंकि इसे किसी भी समय हटाया जा सकता है। इसका उपयोग करने से बचने का प्रयास करें।" - दूसरों को एक क्लिक बचाने के लिए, आपके द्वारा शामिल किए गए dev.moz लिंक से।
क्रिस

2

एलेक्स के जवाब के विकल्प के रूप में:

आप एक कैनवस ड्राइंग के बजाय एक एसवीजी ड्राइंग का उपयोग कर सकते हैं। वहां आप सीधे खींची गई डोम ऑब्जेक्ट्स में ईवेंट जोड़ सकते हैं।

उदाहरण के लिए देखें:

पूर्ण स्थिति से बचने के लिए ऑनक्लिक के साथ एक svg छवि वस्तु को क्लिक करने योग्य बनाना


1
उत्साह के लिए खेद है, यह सिर्फ मैं एक समस्या थी जिसके लिए एसवीजी का उपयोग करना स्पष्ट समाधान है, और मैंने आपकी टिप्पणी तक यह नहीं सोचा था ^ ^
एलियास डोर्नेलस

1

आप DOM के divशीर्ष पर भी DOM तत्व रख सकते हैं, जो आपके कैनवास तत्वों का प्रतिनिधित्व करेगा और उसी तरह तैनात रहेगा।

अब आप इन श्रोताओं को ईवेंट श्रोता संलग्न कर सकते हैं और आवश्यक क्रियाओं को चला सकते हैं।


1

कुछ हद तक स्थिर कैनवास पर एक और सस्ते विकल्प के रूप में, एक usemap परिभाषा के साथ एक अतिव्यापी img तत्व का उपयोग करना त्वरित और गंदा है। एक पाई चार्ट की तरह बहुभुज आधारित कैनवास तत्वों पर विशेष रूप से अच्छी तरह से काम करता है।


0

एलेक्स जवाब बहुत साफ है, लेकिन जब संदर्भ का उपयोग करते हुए बारी बारी से यह एक्स, वाई निर्देशांक का पता लगाने के लिए मुश्किल हो सकता है, इसलिए मैंने एक डेमो दिखाया है कि कैसे उस पर नज़र रखना है।

मूल रूप से मैं इस फ़ंक्शन का उपयोग कर रहा हूं और इसे ऑब्जेक्ट को ड्राइंग करने से पहले कोण और उस परी में तय की गई दूरी की मात्रा दे रहा हूं।

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
    };
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.