codememo

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

tipmemo 2023. 10. 30. 21:01
반응형

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

저는 경험이 풍부한 자바 프로그래머이지만 약 10년 만에 처음으로 자바스크립트/HTML5를 보고 있습니다.무엇이 가장 간단한 일이어야 하는지 완전히 난처합니다.

예를 들어, 저는 단지 무언가를 그리고 그것에 이벤트 핸들러를 추가하고 싶었습니다.제가 뭔가 바보 같은 짓을 하고 있다고 확신합니다. 하지만 저는 여기저기를 찾아봤지만, 제안된 것은 아무것도 없습니다(예: 이 질문에 대한 답).클릭시 속성을 추가하여 자바스크립트로 입력)가 작동합니다.파이어폭스 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>

에 그림을 그릴 때canvas요소는 즉시 모드에서 비트맵을 그리는 것입니다.

그려지는 요소(모양, 선, 이미지)에는 사용하는 픽셀과 색상 외에는 표현이 없습니다.

따라서 클릭 이벤트를 받기 위해서는canvas 요소(모양), 클릭 이벤트를 캡처해야 합니다.canvasHTML 요소를 사용하여 요소의 너비/높이 및 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에 대한 행사.canvaselement, 그리고 나서 하나의 형상을 밀어냅니다 (an이라고 불림).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

자바스크립트는 대소문자를 구분합니다.onclickproperty는 이벤트 핸들러를 연결하는 오래된 방법입니다.속성과 함께 하나의 이벤트만 첨부할 수 있으며 HTML을 직렬화할 때 이벤트가 손실될 수 있습니다.

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

다시.' === ".

2021:

HTML5 캔버스에서 추적 가능한 요소를 만들려면 새로운 Path2D() 메서드를 사용해야 합니다.

먼저 터치 또는 마우스 이벤트(예:onclick,ondblclick,oncontextmenu,onmousemove점 좌표를 얻기 위해 캔버스에서event.offsetX그리고.event.offsetY그럼 쓰시오CanvasRenderingContext2D.isPointInPath()아니면CanvasRenderingContext2D.isPointInStroke()마우스가 해당 이벤트에서 요소를 맴돌고 있는지 정확하게 확인합니다.

IsPointInPath:

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

// Create circle
const circle = new Path2D();
circle.arc(150, 75, 50, 0, 2 * Math.PI);
ctx.fillStyle = 'red';
ctx.fill(circle);

// Listen for mouse moves
canvas.addEventListener('mousemove', function(event) {
  // Check whether point is inside circle
  if (ctx.isPointInPath(circle, event.offsetX, event.offsetY)) {
    ctx.fillStyle = 'green';
  }
  else {
    ctx.fillStyle = 'red';
  }

  // Draw circle
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.fill(circle);
});
<canvas id="canvas"></canvas>

IsPointInStroke:

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

// Create ellipse
const ellipse = new Path2D();
ellipse.ellipse(150, 75, 40, 60, Math.PI * .25, 0, 2 * Math.PI);
ctx.lineWidth = 25;
ctx.strokeStyle = 'red';
ctx.fill(ellipse);
ctx.stroke(ellipse);

// Listen for mouse moves
canvas.addEventListener('mousemove', function(event) {
  // Check whether point is inside ellipse's stroke
  if (ctx.isPointInStroke(ellipse, event.offsetX, event.offsetY)) {
    ctx.strokeStyle = 'green';
  }
  else {
    ctx.strokeStyle = 'red';
  }

  // Draw ellipse
  ctx.clearRect(0, 0, canvas.width, canvas.height);
  ctx.fill(ellipse);
  ctx.stroke(ellipse);
});
<canvas id="canvas"></canvas>

여러 요소가 있는 예제:

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');

const circle = new Path2D();
circle.arc(50, 75, 50, 0, 2 * Math.PI);
ctx.fillStyle = 'red';
ctx.fill(circle);

const circletwo = new Path2D();
circletwo.arc(200, 75, 50, 0, 2 * Math.PI);
ctx.fillStyle = 'red';
ctx.fill(circletwo);

// Listen for mouse moves
canvas.addEventListener('mousemove', function(event) {
  // Check whether point is inside circle
  if (ctx.isPointInPath(circle, event.offsetX, event.offsetY)) {
    ctx.fillStyle = 'green';
    ctx.fill(circle);
  }
  else {
    ctx.fillStyle = 'red';
    ctx.fill(circle);
  }
  
    if (ctx.isPointInPath(circletwo, event.offsetX, event.offsetY)) {
    ctx.fillStyle = 'blue';
    ctx.fill(circletwo);
  }
  else {
    ctx.fillStyle = 'red';
    ctx.fill(circletwo);
  }
  
});
html {cursor: crosshair;}
<canvas id="canvas"></canvas>

확인할 동적 요소 목록이 있는 경우 다음과 같이 루프에서 확인할 수 있습니다.

const canvas = document.getElementById('canvas');
const ctx = canvas.getContext('2d');
var elementslist = []

const circle = new Path2D();
circle.arc(50, 75, 30, 0, 2 * Math.PI);
ctx.fillStyle = 'red';
ctx.fill(circle);

const circletwo = new Path2D();
circletwo.arc(150, 75, 30, 0, 2 * Math.PI);
ctx.fillStyle = 'red';
ctx.fill(circletwo);

const circlethree = new Path2D();
circlethree.arc(250, 75, 30, 0, 2 * Math.PI);
ctx.fillStyle = 'red';
ctx.fill(circlethree);

elementslist.push(circle,circletwo,circlethree)

document.getElementById("canvas").addEventListener('mousemove', function(event) {
event = event || window.event;
var ctx = document.getElementById("canvas").getContext("2d")

for (var i = elementslist.length - 1; i >= 0; i--){  

if (elementslist[i] && ctx.isPointInPath(elementslist[i], event.offsetX, event.offsetY)) {
document.getElementById("canvas").style.cursor = 'pointer';
    ctx.fillStyle = 'orange';
    ctx.fill(elementslist[i]);
return
} else {
document.getElementById("canvas").style.cursor = 'default';
    ctx.fillStyle = 'red';
    for (var d = elementslist.length - 1; d >= 0; d--){ 
    ctx.fill(elementslist[d]);
    }
}
}  

});
<canvas id="canvas"></canvas>


출처:

알렉스의 대답에 대한 대안으로:

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

예를 들어 다음을 참조합니다.

svg 이미지 개체를 클릭 한 번으로 클릭 가능하도록 설정하여 절대 위치 지정 방지

다음 기사를 추천합니다. HTML5 캔버스를 위한 영역 탐지다양한 상황을 겪는 캔버스 모양의 클릭 이벤트 청취 방법.

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

아마 답이 많이 늦었겠지만, 저는 이것을 제 것을 준비하면서 읽었습니다.70-480검사를 해보니 효과가 있었습니다.

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

이벤트를 다음과 같이 표시합니다.onclick대신에onClick.

JS B의 예.

DOM 요소를 넣을 수도 있습니다.div캔버스 요소를 나타내며 동일한 방식으로 배치될 수 있는 캔버스 위.

이제 이벤트 청취자를 이 디브에 연결하고 필요한 작업을 실행할 수 있습니다.

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

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
    };
}

언급URL : https://stackoverflow.com/questions/9880279/how-do-i-add-a-simple-onclick-event-handler-to-a-canvas-element

반응형