ホームページ  >  記事  >  ウェブフロントエンド  >  HTML5 Canvas のイベント処理の概要

HTML5 Canvas のイベント処理の概要

黄舟
黄舟オリジナル
2016-12-16 10:04:451308ブラウズ

DOM は Web フロントエンド分野で非常に重要なコンポーネントです。DOM は HTML 要素を処理するときだけでなく、グラフィック プログラミングでも使用されます。たとえば、SVG 描画では、さまざまなグラフィックスが DOM ノードの形式でページに挿入されます。これは、グラフィックスを DOM メソッドを使用して操作できることを意味します。たとえば、要素がある場合、jquery を直接使用してクリック イベント $('#p1').click(function(){…})" を追加できます。ただし、この DOM 処理方法は、現在では適用できません。 HTML5 Canvas は別のメカニズムを使用します。Canvas 上にどれだけ多くのグラフィックスが描画されても、実際には Canvas 自体は Canvas の一部であり、個別に取得することはできないため、JavaScript イベントを直接追加することはできません。

Canvas. 制限事項

Canvas では、すべてのグラフィックがフレーム上に描画され、js は描画済みのグラフィック要素を取得できません。 :

コードは次のとおりです:

cvs = document.getElementById('mycanvas');

ctx = Canvas.getContext('2d');

theRect = ctx.rect(10, 10, 100, 100 );

ctx.ストローク() ;

console.log(theRect); //unknown

このコードは、canvasタグ内に四角形を描画します まず、グラフィックスを描画するrectメソッドには何もないことがわかります。ブラウザの開発者ツールを開くと、戻り値が存在しないことがわかります。canvas タグ内には何も追加されておらず、js で取得した Canvas 要素と現在のコンテキストには何も含まれていないことがわかります。新しいグラフィックを示すコンテンツ

つまり、フロントエンドで一般的に使用される dom メソッドは、canvas では使用されません。たとえば、上の Canvas 内の四角形をクリックすると、実際には Canvas 要素全体をクリックすることになります。

Canvas 要素にイベントをバインドする

イベントは Canvas 要素レベルまでしか到達できないため、さらに先に進みたい場合は、Canvas 内のどのグラフィック上でクリックが発生したかを特定し、処理用のコードを追加する必要があります。イベントを Canvas 要素にバインドし、イベントが発生したら、イベント オブジェクトの位置を確認し、その位置をどのグラフィックスがカバーしているかを確認します。上記の例では、範囲をカバーする四角形が描画されます。 x 軸で 10 ~ 110、y 軸で 10 ~ 110 の範囲でマウスをクリックしている限り、四角形をクリックしたと見なされ、四角形を手動でトリガーして処理できます。クリック イベント: アイデアは実際には比較的単純ですが、実装はまだ少し複雑です。この判定プロセスの効率を考慮する必要があるだけでなく、いくつかの場所でイベントの種類を再判定する必要があります。 Canvas 内のバブリング メカニズムを再定義する必要があります

最初に行うことは、Canvas 要素にイベントをバインドすることです。たとえば、クリック イベントを Canvas 内のグラフィックにバインドする場合は、イベントをプロキシする必要があります。 Canvas 要素を介して:

コードは次のとおりです:

cvs = document.getElementById('mycanvas ');

cvs.addEventListener('click', function(e){

//...

}, false);

次に、イベント オブジェクトが発生する場所、イベント オブジェクトの LayerX と LayerX を決定する必要があります。 e LayerY 属性は、Canvas 内部座標系の座標を表します。ただし、Opera はこの属性をサポートしておらず、Safari はこの属性を削除する予定であるため、いくつかの互換性のある記述メソッドを作成する必要があります:

コードは次のとおりです:

function getEventPosition(ev){

var x, y;

if (ev.layerX || ev .layerX == 0) {

x = ev.layerX;

y = ev.layerY;

} else if (ev.offsetX || ev.offsetX == 0) { // Opera

x = ev .offsetX;

y = ev.offsetY;

}

return {x: .

イベント オブジェクトの座標位置がわかったので、キャンバス内のどのグラフィックスがこの座標をカバーするかを決定する必要があります。

isPointInPath メソッド

Canvas の isPointInPath メソッドは、現在のコンテキスト グラフィックが特定の座標をカバーしているかどうかを判断できます。例:

コードは次のとおりです:

cvs = document.getElementById('mycanvas');

ctx = Canvas .getContext('2d');

ctx.rect(10, 10, 100, 100);

ctx.ストローク();

ctx.isPointInPath(50, 50); //true

ctx.isPointInPath (5 , 5); //false

次に、四角形上でクリックイベントが発生するかどうかのイベント判定を追加します:

コードは以下の通りです:

cvs.addEventListener('click', function(e) {

p = getEventPosition(e);

if(ctx.isPointInPath(p.x, p.y)){

//四角形がクリックされました

}

}, false);

以上が基本的なメソッドですただし、上記のコードには制限があります。 isPointInPath メソッドは現在のコンテキスト内のパスのみを決定するため、Canvas 内に複数のグラフィックが描画されている場合、イベントは最後のグラフィックのコンテキストに基づいてのみ決定できます。例:

コードは次のとおりです:

cvs = document.getElementById('mycanvas');

ctx = Canvas.getContext('2d');

ctx.beginPath();

ctx.rect (10、10、100、100);

ctx.ストローク();

ctx.isPointInPath(20, 20); //true

ctx.beginPath();

ctx.rect(110, 110, 100, 100);

ctx.ストローク( ; グラフィックパス、および以前に描画されたパスを遡って判断することはできません。この問題の解決策は、クリック イベントが発生したときに、すべてのグラフィックスを再描画し、描画されたグラフィックスごとに isPointInPath メソッドを使用して、イベントの座標がグラフィックスの範囲内にあるかどうかを判断することです。

ループ再描画とイベントバブリング

ループ再描画を実装するには、グラフィックスの基本パラメータを事前に保存する必要があります:

コードは次のとおりです:

arr = [

{x:10, y: 10, width:100, height:100},

{x:110, y:110, width:100, height:100}

];

cvs = document.getElementById('mycanvas');

ctx = Canvas .getContext('2d');

draw();

functiondraw(){

ctx.clearRech(0, 0, cvs.width, cvs.height);

arr.forEach(function( v) {

ctx.beginPath();

ctx.rect(v.x, v.y, v.width, v.height);

ctx.ストローク();

});

}

上記コードは事前に 2 つの四角形の基本パラメータを保存しておきます。draw メソッドが呼び出されるたびに、これらの基本パラメータが循環的に呼び出され、2 つの四角形が描画されます。ここでは、再描画時にキャンバスをクリアするために、clearRect メソッドも使用されています。次に行うことは、イベント デリゲートを追加し、再描画時にコンテキストごとに isPointInPath メソッドを使用することです:

コードは次のとおりです:

cvs.addEventListener('click', function(e){

p = getEventPosition( e);

draw(p);

}, false);

イベントが発生すると、イベントオブジェクトの座標がdrawメソッドに渡されて処理されます。ここで、draw メソッドにいくつかの小さな変更を加える必要があります:

コードは次のとおりです:

functiondraw(p){

var who = [];

ctx.clearRech(0, 0, cvs.width , cvs.height) ;

arr.forEach(function(v, i){

ctx.beginPath();

ctx.rect(v.x, v.y, v.width, v.height);

ctx.ストローク();

if(p && ctx.isPointInPath(p.x, p.y)){

//イベント座標が渡された場合はisPointInPathを使って判断する

//現在の環境が座標をカバーしている場合は、現在の環境のインデックス値を配列に入れます

who.push(i);

}

});

//配列内のインデックス値に従って、arr内の対応する要素を見つけることができます配列。

return who;

}

上記のコードでは、クリックイベントが発生するとdrawメソッドで再描画が行われ、再描画処理中に各グラフィックがイベント座標をカバーしているかどうかを確認し、判定が真であれば、グラフィックをクリックするには、グラフィックのインデックス値を配列に入れ、最終的にその配列をdrawメソッドの戻り値として使用します。この処理メカニズムでは、Canvas 内に N 個のグラフィックスがあり、その一部が重なっていて、この重なった領域でクリック イベントが発生した場合、draw メソッドの戻り配列には N 個のメンバーが存在します。このとき、配列の最後のメンバーがキャンバスの一番上にあり、最初のメンバーが一番下にあるのと少し似ています。一番上のメンバーは e.target と考えることができます。 、他のメンバーは e.target です。バブル プロセス中に渡されるノードです。もちろん、これは最も単純な処理方法にすぎません。実際に DOM 処理をシミュレートしたい場合は、グラフィックスの親子関係を設定する必要があります。

以上がCanvasイベントハンドリングの基本的な方法です。実際のアプリケーションでは、グラフィックスパラメータをどのようにキャッシュするか、ループの再描画をどのように行うか、イベントのバブリングをどのように処理するかなど、実際の状況に応じて対処する必要があります。また、click のほうが扱いやすいイベントですが、mouSEOver、mouseout、mousemove は一度マウスが Canvas 要素に入ると必ずマウスムーブイベントが発生するため、マウスオーバーやマウスアウトを個別に設定したい場合に便利です。グラフィック、 、マウスの移動ルートを記録し、グラフィックの開始ステータスと終了ステータスを設定する必要もあります。処理ステップが複雑になるにつれて、パフォーマンスの問題にさらに注意を払う必要があります。

上記は HTML5 Canvas のイベント処理の紹介です。その他の関連記事については、PHP 中国語 Web サイト (www.php.cn) をご覧ください。

声明:
この記事の内容はネチズンが自主的に寄稿したものであり、著作権は原著者に帰属します。このサイトは、それに相当する法的責任を負いません。盗作または侵害の疑いのあるコンテンツを見つけた場合は、admin@php.cn までご連絡ください。