1. ホーム
  2. javascript

[解決済み] canvas 要素に簡単な onClick イベントハンドラを追加するにはどうすればよいですか?

2022-04-28 04:50:41

質問

私は経験豊富な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>

解決方法は?

に描画すると 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 要素で、1つの図形をプッシュします(これを 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

JavaScriptでは '" が意味的に同一である場合、レキサはおそらく ['"] を引用しています。

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

に文字列を代入していますね。 onClick プロパティの elem .

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

JavaScriptは大文字と小文字を区別します。また onclick プロパティは、イベントハンドラのアタッチメントとして古風な方法です。このプロパティで指定できるイベントは1つだけであり、HTMLをシリアライズする際にイベントが失われる可能性があります。

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

もう一度 ' === " .