ご存知のとおり、キャンバスはビットマップです。ビットマップでは、絵や線など、さまざまなものを描画できます。では、キャンバス内の特定の画像にクリック イベントを追加したい場合はどうすればよいでしょうか。そして、js はキャンバス イベントを監視することしかできません。明らかに、この画像は存在せず、dom 内の画像はキャンバスに描画されているだけです。次に、キャンバス内の各画像にイベント バインディングを実装します。
まず実装原理について説明します。実際に関連するイベントをキャンバスにバインドします。画像が配置されているキャンバスの座標を記録することで、イベントがどの画像に作用するかを判断します。この点では、イベント エージェントに少し似ているように感じます。ただし、実装はまだ少し複雑です。
ps: ts で次のコードを書きました。es6 として読み込むだけで、多少の違いがあるかどうかを確認できます。
Typescript のドキュメント (typescript は非常に使いやすいので、詳しく学ぶことをお勧めします)。
1. 画像とキャンバスの間の接続を確立します (ここでは画像の代わりにカラーブロックを使用します)ここでは、単にレンダリングするのではなく、カラー ブロックとキャンバスの間に特定の接続を確立する必要があります。カラーブロックの座標、幅、高さも記録します。段階的に実行してみましょう
まず、キャンバスを作成するための基本的な HTML ページを作成します。
<!DOCTYPE html><html lang=ja><head> <meta charset=UTF-8> <meta name=viewport content=width=device-width、initial-scale=1.0> <meta http-equiv=X-UA -互換コンテンツ=ie=edge> <title>canvas イベント</title> <style> html, body { height: 100% } キャンバス {background: #fff; 表示: ブロック; マージン: 0 自動; </style></head><body> <canvas width=500 height=500 id=canvas></body>
次に、Canvas クラスを定義する必要があります。このクラスにはどのような機能が必要ですか?
カラー ブロックには独自のパラメータもいくつかあるため、拡張を容易にするために、このタイプに必要な関数もカラー ブロックに定義します。
幅、高さ、色、座標 (x、y)、および Canvas インスタンスを最初に決定しましょう。
OK 書き始めます
// Canvas クラス class Canvas { blockList: Block[] ctx: any Canvas: any createBlock (option) { option.Canvas = this this.blockList.push(new Block(option)) this.painting() } rendering (block) { // カラーブロック関数のレンダリング this.ctx.fillStyle = block.color this.ctx.fillRect(block.x, block.y, block.w, block.h) } Painting () { //コンテナ内のすべてのカラー ブロックをキャンバスにレンダリングします。 // キャンバスをクリアします (古いものはレンダリング前にクリアする必要があります) this.ctx.fillStyle = '#fff' this.ctx.fillRect(0, 0, this.canvas. width, this .canvas.height) this.blockList.forEach(ele => { this.rendering(ele) }) }constructor (ele) { // 初期化関数 (入力は Canvas) // Set Canvas this.canvas = ele this.ctx = this.canvas.getContext('2d') // カラーブロックコンテナ this.blockList = [] }}class Block { w: 数値 h: 数値 x: 数値 y: 数値 カラー: string Canvas: Canvas階層:numberconstructor ({ w, h, x, y, color, Canvas }) { // カラーブロック関連のプロパティを初期化して設定 this.w = w this.h = h this.x = x this.y = y this.color = カラー this.Canvas = キャンバス }}
以下で Wave を実行してみましょう
//Canvas インスタンスを作成し、幅と高さ 100 ピクセルの青色のカラー ブロック、位置 (100,100)、(300,100)、赤色と青色のカラー ブロックを追加します。 var Canvas = new Canvas(document.getElementById('canvas')) Canvas .createBlock({ // 赤 x: 100、y: 100、w: 100、h: 100、色: '#f00' }) Canvas.createBlock({ // 青 x: 100, y: 100, w: 300, h: 100, color: '#00f' })
実行結果は次のとおりです。
2. カラーブロックにクリックイベントを追加するここでは、クリック イベントをカラー ブロックに直接追加することはできないため、座標を使用して、現在どのカラー ブロックがクリックされているかを判断する必要があります。
class Block { // ...コードの一部を省略 checkBoundary (x, y) { // 境界メソッドを決定 return x > this.x && x < (this.x + this.w) && y > this.y && y < (this.y + this.h) } MousedownEvent () { // クリックイベント console.log(`色 ${this.color} のカラーブロックをクリックしました`) }}class Canvas { // .. .省略された部分コード コンストラクター(ele) { this.canvas = ele this.ctx = this.canvas.getContext('2d') this.blockList = [] // イベント バインディング (ここで注意すべき点が 1 つあります。ここでは、bind メソッドを使用しました。 is MousedownEvent メソッドの this ポインタを Canvas に切り替えるため) this.canvas.addEventListener('click', this.mousedownEvent.bind(this)) // クリック イベント} MousedownEvent () { //クリックイベント const x = e.offsetX const y = e.offsetY // ここでは、クリックの座標をすべてのカラーブロックに渡し、境界判定メソッドを使用してクリックが内側かどうかを判定します。 「はい」の場合、カラー ブロックのイベント メソッドを実行します。 this.blockList.forEach(ele => { if (ele.checkBoundary(x, y)) ele.mousedownEvent(e) }) }}
これまで、対応するクリック イベントを異なるキャンバスの異なるカラー ブロックにバインドする実装を行ってきました。ただし、このクリック イベントは完全ではありません。これまで階層の概念を導入していなかったためです。階層の概念は、重なっている 2 つのカラー ブロックをクリックすると、両方がトリガーされることを意味します。したがって、カラー ブロックに階層属性を追加する必要もあります。カラーブロックをクリックしてカラーブロックを変更すると、そのカラーブロックのレベルが最高レベルに上がります。
class Block { // ...コードコンストラクターの一部を省略します ({ w, h, x, y, color, Canvas,hierarchy }) { // カラーブロックに関連するプロパティを初期化して設定します this.w = w this .h = h this. x = x this.y = y this.color = color this.Canvas = Canvas this.hierarchy = 0 }}class Canvas { // ...コードコンストラクターの一部を省略 (ele) { this .canvas = これ.ctx = this.canvas.getContext('2d') this.blockList = [] // イベント バインディング (ここで注意すべき点が 1 つあります。ここでは、bind メソッドを使用して、mousedownEvent メソッドの this ポインタを Canvas に切り替えました) this .canvas .addEventListener('click', this.mousedownEvent.bind(this)) // クリックイベント this.nowBlock = null // 現在選択されているカラーブロック} createBlock (option) { //カラーブロック作成関数(ここでのBlockはカラーブロックのクラスです) option.Canvas = this // 最新のカラーブロック作成レベルを最上位にする必要があります option.hierarchy = this.blockList.length this.blockList.push(new Block (option)) this.rendering() } MousedownEvent (e) { // クリックイベント const x = e.offsetX const y = e.offsetY //ポイント内の最高レベルのカラー ブロックを取得します this.nowBlock = (this.blockList.filter(ele => ele.checkBoundary(x, y))).pop() // キャプチャされたカラー ブロックがない場合は、直接終了します。 (!this .nowBlock) return // クリックされたカラー ブロック レベルを最高に上げます this.nowBlock.hierarchy = this.blockList.length // (小さいものから大きいものへ) 並べ替えます this.blockList.sort((a, b) = > a.hierarchy - b.hierarchy) // 階層を0から再割り当て this.blockList.forEach((ele, idx) => ele.hierarchy = idx) // 逆順に再ソートしてから再レンダリングします。 this.painting() this.nowBlock.mousedownEvent(e) // 選択したカラー ブロックのイベントのみをトリガーします}}// ここでは、赤色のカラー ブロックと重なる 3 番目のカラー ブロックも追加する必要があります。 Canvas.createBlock({ x: 150、y: 150、w: 100、h: 100、色: '#0f0'})
Canvas の MousedownEvent メソッドのコードは、主に少し複雑なため、少し複雑です。
実行後の効果は以下の通りです。
3. 異なる色のブロックをドラッグ アンド ドロップします。上記では、さまざまなカラーブロックの取得とそのレベルの変更を実装しました。次に、主にマウスの移動中およびマウスの最初のクリック時の位置座標の変化を取得するために、カラー ブロックのドラッグを実装する必要があります。この原理は通常の DOM ドラッグ アンド ドロップ実装と同じです。
カラーブロックをクリックした位置と、カラーブロックの左端と上端からの距離(disX、disY)を取得します。
マウスが移動すると、キャンバスの左および上からのマウスの現在の距離から (disX、disY) が減算されます。これがカラー ブロックの x 座標と y 座標です。
class Block { // ...コードの一部を省略 MousedownEvent (e: MouseEvent) { /* ここでの disX と disY の計算方法: e.offsetX はマウスのクリックとキャンバスの左側の間の距離を取得し、 this.x はカラー ブロック距離です。キャンバスの左側までの距離です。 e.offsetX-this.x は、カラー ブロックの左側までの距離です。これがわかりやすいと思います*/ const disX = e.offsetX - this.x // クリックしたときのカラーブロックの左側からの距離 const disY = e.offsetY - this.y // 上端からの距離クリックされたときのカラー ブロック // マウス スライド イベントをバインドします。ここで、mouseEvent.offsetX はマウスとキャンバスの左側の間の距離でもあり、mouseEvent.offsetX - disX はカラー ブロックの x 座標です。同様に、yも同様に計算されます。最後に、再レンダリングするだけです。 document.onmousemove = (mouseEvent) => { this.x =mouseEvent.offsetX - disX this.y =mouseEvent.offsetY - disY this.Canvas.painting() } // マウスを離すとすべてのイベントをクリア document.onmouseup = ( ) => { document.onmousemove = document.onmousedown = null } // console.log(`クリックされたカラー ブロック 22`、色 ${this.color}) }}
効果は次のとおりです。
完全なコードを以下に貼り付けます (HTML および呼び出しメソッドは含まれません)。この例は、キャンバス内のコンテンツにイベントをバインドする単純な実装です。カラー ブロックを画像に置き換えるなど、より複雑な実装も可能です。ドラッグするだけでなく、画像の拡大、回転、削除などができます。
class Canvas { blockList: Block[] ctx: any Canvas: any nowBlock: Block createBlock (option) { option.hierarchy = this.blockList.length option.Canvas = this this.blockList.push(new Block(option)) this. Painting() } レンダリング (ブロック) { this.ctx.fillStyle = block.color this.ctx.fillRect(block.x, block.y, block.w, block.h) } Painting () { // キャンバスをクリア this.ctx.fillStyle = '#fff' this.ctx.fillRect(0, 0, this.canvas.width, this.canvas.height) this.blockList.forEach(ele => { this.rendering(ele) }) } MousedownEvent (e: MouseEvent) { // クリックイベント const x = e.offsetX const y = e.offsetY //ポイント内の最高レベルのカラー ブロックを取得します this.nowBlock = (this.blockList.filter(ele => ele.checkBoundary(x, y))).pop() // キャプチャされたカラー ブロックがない場合は、直接終了します。 (!this .nowBlock) return // クリックされたカラー ブロック レベルを最高に上げます this.nowBlock.hierarchy = this.blockList.length // (小さいものから大きいものへ) 並べ替えます this.blockList.sort((a, b) = > a.hierarchy - b.hierarchy) // 階層を0から再割り当て this.blockList.forEach((ele, idx) => ele.hierarchy = idx) // 逆順に再ソートしてから再レンダリングします。 this.painting() this.nowBlock.mousedownEvent(e) // this.blockList.forEach(ele => { // if (ele.checkBoundary(x, y)) ele.clickEvent(e) // }) } コンストラクター(ele) { this.canvas = ele this.ctx = this.canvas.getContext('2d') this.blockList = [] //イベント バインディング this.canvas.addEventListener('mousedown', this.mousedownEvent.bind(this)) }}class Block { w: 数値 h: 数値 x: 数値 y: 数値 color: 文字列 Canvas: Canvas 階層: 数値 コンストラクター ( { w, h, x, y, カラー, Canvas, 階層 }) { this.w = w this.h = h this.x = x this.y = y this.color = color this.Canvas = Canvas this.hierarchy = 階層 } checkBoundary (x, y) { return x > this.x && x < (this.x + this.w) && y > this.y && y < (this.y + this.h) } MousedownEvent (e: MouseEvent) { const disX = e.offsetX - this.x const disY = e.offsetY - this.y document.onmousemove = (mouseEvent) => { this.x = MouseEvent.offsetX - disX this.y = MouseEvent.offsetY - disY this.Canvas.painting() } document.onmouseup = () => { document.onmousemove = document.onmousedown = null } // console.log(`カラー ${this.color} のカラー ブロック 22 がクリックされました`) }}
以上がこの記事の全内容です。皆様の学習のお役に立てれば幸いです。また、VeVb Wulin Network をご支援いただければ幸いです。