캔버스 요소에 간단한 onClick 이벤트 핸들러를 어떻게 추가합니까?


128

저는 숙련 된 Java 프로그래머이지만 약 10 년 만에 처음으로 JavaScript / HTML5를 살펴보고 있습니다. 나는 가장 간단한 것이 무엇인지에 완전히 빠져 있습니다.

예를 들어 무언가를 그리고 이벤트 핸들러를 추가하고 싶었습니다. 나는 바보 같은 짓을하고 있다고 확신하지만 모든 것을 검색했지만 제안 된 것은 없습니다 (예 :이 질문에 대한 답변 : JavaScript로 입력하기 위해 onclick 속성 추가 )이 작동합니다. 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>


8
onclick대신 사용onClick
noob

1
이러한 시도가 작동하지 않은 이유를 자세히 설명하기 위해 ... 호출 alert()<script>함수를 정의하는 대신 직접 호출하기 때문에 처음 몇 개의 주석에 즉시 경고가 표시 됩니다 alert(). 나머지는의 대문자로 인해 아무 것도하지 않습니다 onclick.
LarsH

이 lib 디렉토리를 사용할 수 있습니다 jsfiddle.net/user/zlatnaspirala/fiddles 에서 모습을 bitbucket.org/nikola_l/visual-js . 당신은 많은 기능 + 얻을 것이다
니콜라 루킥

답변:


223

canvas요소에 그리면 비트 맵을 즉시 모드로 그리는 것 입니다.

요소 그려 (도형, 선, 이미지)가 그들이 사용하는 화소와 그 외에 어떠한 색이 없다.

따라서 요소 (모양)에서 클릭 이벤트 를 얻으려면 요소의 너비 / 높이 및 x / y 오프셋을 저장하는 경우 HTML 요소 에서 클릭 이벤트를 캡처 하고 수학을 사용하여 클릭 한 요소를 결정해야합니다. .canvas canvas

요소에 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

JavaScript는 대소 문자를 구분합니다. 이 onclick속성은 이벤트 처리기를 연결하는 오래된 방법입니다. 속성에 하나의 이벤트 만 첨부 할 수 있으며 HTML을 직렬화 할 때 이벤트가 유실 될 수 있습니다.

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

다시 ' === ".


흠 ... 오해하는 경우 용서하십시오-캔버스 요소에서 클릭 이벤트를 캡처하지 않습니까? 나는 당신이 무슨 뜻인지 모르겠어요 무엇을 클릭 한 요소입니다. 이 페이지에는 하나의 요소 만 있습니다.
Jer

그는 "캔버스 내의 어떤 요소"를 의미했습니다.
Jovan Perovic

1
고마워요.하지만 마지막에 완전히 명확하지는 않지만. 여기 예제를 따르고 있습니다 : developer.mozilla.org/en/DOM/element.onclick (설명 된 익명 함수 사용) 및 범위를 캔버스로 변경하더라도 작동합니다. 따라서 내가 잘못하고있는 것을보기 위해 천천히 그들의 예를 내 것으로 바꾸는 것은 어렵지 않습니다. 자세한 답변 감사합니다! 나의 다양한 시도가 왜 틀린지에 대한 설명이 특히 도움이되었습니다.
Jer

1
@Jer 걱정하지 마십시오. 궁금한 점이 더 있으면 Twitter에 @alexdickson 으로 게시하고 핑 (Ping) 해주십시오 .
alex

1
@HashRocketSyntax 잘 동작하고 메모리에있는 객체의 위치를 ​​업데이트하고 그 정의를 사용하여 렌더링합니다.
alex

4

아마도 답변에 매우 늦었지만 70-480시험 을 준비하는 동안 이것을 읽었으며 이것이 효과가 있음을 알았습니다.

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

onclick대신 이벤트 를 확인하십시오 onClick.

JS 빈 예.


3

다음 기사를 추천합니다. HTML5 캔버스의 히트 영역 감지 및 다양한 상황을 거치는 캔버스 셰이프에서 이벤트를 클릭하는 방법 .

그러나 addHitRegionAPI를 다루지 않는 것이 가장 좋은 방법입니다 (수학 함수 및 / 또는 비교를 사용하면 오류가 발생하기 쉽습니다). 이 접근 방식은 developer.mozilla에 자세히 설명 되어 있습니다.


"[ addHitRegion]은 (는) 사용되지 않습니다. 일부 브라우저에서는 여전히 작동하지만 언제든지 제거 할 수 있으므로 사용하지 않는 것이 좋습니다. 사용하지 마십시오." -포함 된 dev.moz 링크에서 다른 사람의 클릭을 저장합니다.
크리스

2

alex의 답변에 대한 대안으로 :

캔버스 도면 대신 SVG 도면을 사용할 수 있습니다. 여기에서 그려진 DOM 객체에 직접 이벤트를 추가 할 수 있습니다.

예를 들어 :

절대 위치를 피하면서 onclick으로 svg 이미지 객체를 클릭 가능하게 만들기


1
열정에 대해 죄송합니다. SVG를 사용하는 것이 확실한 해결책이라는 문제가 있었으며 귀하의 의견이 생길 때까지 생각하지 못했습니다 ^^
Elias Dorneles

1

div캔버스 요소를 표현하고 같은 방식으로 배치되는 캔버스 위에 DOM 요소를 넣을 수도 있습니다.

이제이 div에 이벤트 리스너를 연결하고 필요한 조치를 실행할 수 있습니다.


1

다소 정적 인 캔버스의 또 다른 저렴한 대안으로 usemap 정의와 함께 오버레이 img 요소를 사용하는 것은 빠르고 더럽습니다. 원형 차트와 같은 다각형 기반 캔버스 요소에서 특히 잘 작동합니다.


0

Alex Answer 는 매우 깔끔하지만 컨텍스트 회전을 사용할 때 x, y 좌표를 추적하기가 어려울 수 있으므로이를 추적 하는 방법을 보여주는 데모 를 만들었습니다 .

기본적으로 나는이 기능을 사용하고 있으며 객체를 그리기 전에 천사에게 이동 한 각도와 거리를 제공합니다.

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
    };
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.