web-dev-qa-db-ja.com

HTMLキャンバスを介してクリックを取得します

Html5キャンバス要素でマウスクリックを受け取る方法について多くの質問があります。キャンバスをオーバーレイとして使用していますが、マウスクリックが下の要素に到達しません。キャンバスに画像を読み込んでいるので、それが問題になるかもしれないと思いましたが、空のキャンバスでも試してみたところ、同じ結果が得られました。

次に例を示します。画像付き: http://www.1luckypixel.com/paranormal/canvas_test.html リンクはgoogleに移動しますが、登録されていません。

キャンバスはデフォルトでマウスに対して透過的であると私は理解していますか?

20
JoeM05

クロスブラウザ機能が要件でない場合は、簡単な解決策があります。 SVG以外の要素(webkit、Mozilla、その他、特にIEではない)でサポートしているブラウザーでは、pointer-eventsというcssプロパティを使用できます。 )。 MDNから:

「CSSプロパティpointer-eventsを使用すると、作成者は特定のグラフィック要素がマウスイベントのターゲットになる可能性がある状況(存在する場合)を制御できます。このプロパティが指定されていない場合、visiblePainted値の同じ特性がSVGコンテンツに適用されます。

要素がマウスイベントのターゲットではないことを示すことに加えて、値noneは、マウスイベントに要素を「通過」し、代わりにその要素の「下」にあるものをターゲットにするように指示します。

警告:非SVG要素のCSSでのポインターイベントの使用は実験的なものです。現在CSS3UIドラフト仕様で定義されており、CSS4に延期する議論があります。 "

少なくとも、Modernizrを使用して、ポインターイベントのサポートを検出し、それをサポートしていないブラウザーで Simon Sarrisの回答 に記載されている不透明度のトリックを実行できます。

また、アプリケーションがGoogleマップに固有である場合は、キャンバスをGoogleマップオーバーレイとして挿入できるため、問題をまとめて回避できます。

例: http://www.patrick-wied.at/static/heatmapjs/demo/maps_heatmap_layer/gmaps.php

9
Bojin Li

キャンバスの上にリンクを配置できないと仮定します...

新しい/まともなブラウザの場合は、次のCSSを使用するだけです。

#canvas { pointer-events:none; }

そして、IE +古いブラウザ(jQueryへの依存を取り除くことができます)の汚い回避策:

jQuery('#canvas').click(function(e) {
    window.location = jQuery('#element-under-canvas').attr('href');
});

明らかに、これは現状のアンカーのみをサポートしており、キャンバスの下にある特定の要素を知る必要があります(または、jQueryセレクターマジックを使用して見つけることができます)。

5
Dunc

キャンバスを次のように設定することで、これを実現できました。

<div>
    <a href='#'>my link</a>
    <canvas></canvas>
</div>

次に、CSSで次のように設定します。

canvas {
    display: block;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    position: absolute;
    z-index:-1; /* NOT SURE HOW SUPPORTED THIS IS, IT WORKED IN CHROME */
}

実行時にキャンバスにペイントしたものに関係なく、div内のリンクはクリック可能でした。

お役に立てれば!

2
Steve Woods

簡単に言うと、クリックスルーはできません。

しかし、2番目に短い答えは、あなたは本当にあなたの心が望むことは何でもできるということです!あなたはただ解決策で少し奇妙になることをいとわない必要があります。

私が考える最初の方法は少し腹立たしいですが簡単です:キャンバスの後ろのすべてのアイテムについて、キャンバスの前に同様の秘密のアイテムを作成します。次に、必要なイベントをシークレットアイテムに配置します。

<!-- A visible button behind the canvas -->
<button id="but" type="button" style="position: absolute; top: 100px; left: 100px;">Click Me!</button>

<canvas id="can" width="500" height="500" style="position: absolute;"></canvas>

<!-- A near copy of the visible button, but this one is invisible and in front of the canvas! -->
<button id="but" type="button" onclick="alert('click!')" style="position: absolute; top: 100px; left: 100px; opacity: 0;">Click Me!</button>

そのコードの動作を確認したい場合 ここをクリック

キャンバスの後ろにクリック可能にしたいものが100個ある場合は、もう少し非常識でありながら保守しやすい方法がありますが、後ろにクリックしたいものが1〜3個しかない場合は、おそらくこれが最も簡単です。キャンバス。

2
Simon Sarris

Simon Sarrisの回答から借用すると、状況によっては、キャンバスとコントロールを同じ平面上に配置する方が簡単な場合があります。コントロールによっては、キャンバスをコントロールの上に描画できるとは限りませんが、Joeの元の質問ではこれは必要ないようです。重要なことは、キャンバスとコントロールが同じZ平面上にあり、両方とも「position」キーワードを使用するスタイルを持ち、コントロールのHTMLがcanvasステートメントの後にあることを確認することです。以下は、このメソッドを使用してコントロールと組み合わせたキャンバスの例です。

<canvas id="can" width="500" height="500" style="z-index:2; position: absolute;"></canvas>
<!-- Put text and a link on the same plane as the canvas -->
<div style="position: relative; z-index: 2;">
   <a href="http://www.google.com/">Click</a> this Google link.
</div>
1
Frank

Z-indexを動的に変更する方が良いと思います。コントロールを使用する必要がある場合は、z-indexをcanvasよりも高く設定します。キャンバスを使用する必要がある場合は、コントロールよりも高いz-indexを設定します。これを行う正確な方法は、状況によって異なります。マウスダウン/マウスアップイベント、または一部の領域でのマウス移動をリッスンできます。

これが私がこの問題を解決した方法です...

私は丸いユーザーインターフェースデバイスを持っています(正方形であるプレーンなHTML5キャンバスに描かれています)。円だけが色付けされ、キャンバスの残りの部分は透明なので、クリックしていきたいと思います。四角い帆布の角の下に、キネティックJSステージの形があります。

通常キャンバスをクリックすることはできません。

ただし、クリックイベントをキネティックシェイプに送信し、次のようにそのシェイプ内でイベントリスナーをアクティブ化できます。

    $( '#myCanvasUserInterfaceLayer' ).on( 'click', function( e ) {

        var pos = getMousePos( e );
        var obscuredKineticShape = kineticLayer.getIntersection( pos );

   // (Note: console.log(obscuredKineticShape) and you find that 
   // 'getIntersection' returns an object with the topmost shape 
   //  at the click point on the kinetic stage within it, called 'shape').

        obscuredKineticShape.shape.fire( 'mousedown' ); 

    });

     function getMousePos( e ) {

        return {
          x: e.pageX,
          y: e.pageY
        };
      }
0
JSdc

この手順がどのように行われるかはわかりませんが、SimonSarrisが実際にコメントで解決策を提供しました。

残念ながら、この場合、他の方法は機能しません。 :(ただし、必要なものに近いものができるまで、不透明度をいじることができます。これは、背後にキャンバスを表示する透明なマップの例です。緑色のボックスが上にあるように見えますが、実際には透けて見えます。 jsfiddle.net/un9yW/11 もちろん、この方法を実行すると、マップの一部を完全に覆う緑色のボックスを作成する方法がないことを意味します。あなたの状況に役立つ他の何かを考えたらお知らせします。– Simon Sarris7時間前

0
JoeM05