Canvasグラフィック要素での本格的なマウスイベント

問題



JavaScript + Canvasを使用したグラフィックの開発に携わる人々は、グラフィック要素でのマウスイベントの処理の問題に長い間気づいていました。



この問題にはいくつかの解決策があります。

  1. それらをまったく処理しないでください。つまり、グラフィックはインタラクティブではなく、必要ありません。
  2. 各形状の長方形を計算してメモリに保存し、カーソルがこれらの長方形に入ったときにイベントをトリガーします
  3. 長方形、円、線などのさまざまな数式を使用して、各グラフィック要素に個別にアプローチします。




これらのすべての方法には特定の状況での生存権がありますが、イベントを検出する必要がある場合(オプション1を削除)、形状が長方形ではない場合が多く、ターンがあり、形状が幾何学的に正しくない場合は他の変換(オプション2も適切ではありません)、たとえば、スプラインによって滑らかにされた線、凹面を備えたポリゴン(オプション3も忘れられます)、そして最も重要なことには、これらの数字が無数になり、それぞれの座標を保存し、各MouseMoveで並べ替えるとオーバーヘッドになります。 別の方法が助けになります。



ソリューションアプローチ



ピクセルが図のカーソルにどのように当たるかを正確に知る必要があります。 これを行うには、次のことを行います。

シェイプを作成するとき、一意の数値識別子、たとえば1を割り当てます。次に、この識別子をRGB HEX表記の色に変換します- #000001







Figureが配置されているレイヤーの新しいキャンバス要素を作成しましょう。しかし、DOMには追加しません。これはバックグラウンドキャンバスです。

図をメインキャンバスに描画する際、背景に描画しますが、識別子(境界線を含む)に由来する色で描画します。

描画順序が順守されると、バックグラウンドキャンバス上のシェイプが実際のキャンバスと同じ順序で重なり、マウスカーソルがメインキャンバスに沿って移動すると、シェイプ識別子であるバックグラウンドキャンバスのピクセルカラーの座標を確認できることが明らかになりました。これにより、カーソルが図に移動したか、離れたことが明確にわかります。



落とし穴



マウスが移動すると、その下のピクセルの色が決定され、不透明な場合(Alpha = 255)



、形状識別子が決定され、イベントが処理されます。



しかし、すべてがバラ色ではありません。 主に3つの問題があります。



1.スムージング


実際には、すべてのブラウザはデフォルトでレンダリング時にアンチエイリアスを使用します。つまり、Figure内のすべてのピクセルが完全に不透明ではなく、必要な色になるわけではありません。

画像



解決策:

図の境界線を2ピクセル分太くする必要があります(この同じ境界線がない場合は2ピクセルだけ)。 これは周囲のピクセルに追加のノイズを作成しますが、私たちにとっては重要ではなく、ユーザーにも見えないため、これは無視できます。



2.色の融合


2つの形状が交差する場合、同じ平滑化により完全に不透明なピクセルが作成され、その色は1つの形状の色から別の形状の色に移行します。 同時に、この色がまったく異なる場所にあるまったく異なる人物を示す可能性はほとんどありません。 実際に動作するアプリケーションでは、この可能性は非常に低いですが、すべてを提供したいのでしょうか?

画像



解決策:

識別子の信ity性を検証するには、上下左右の4ピクセルの色を見つける必要があります。 それぞれが同じ色であるか、完全に透明ではない場合、識別子は信頼できます。



3.画像


画像を操作する場合、 getImageData



を介して受信したピクセルデータを繰り返し処理し、各不透明ピクセルを形状識別子の色に置き換え、半透明のそれぞれを透明なものに置き換える何らかの種類の画像プロセッサを作成する必要があることは明らかです。



この場合、明確な問題はありません。注意が必要なニュアンスは3つしかありません。







実装



そのため、適切な色でシェイプが描かれた背景キャンバスがすでにあります。 カーソルの下のピクセルの色を取得する方法は? 以下は、カーソルの座標を知ってその下にピクセルを取得する方法を示す抽象コードです。



 //x, y -  ,   var ctx = bgCanvas.getContext("2d"); var pixel = ctx.getImageData(x, y, 1, 1).data; //  4 ,  R, G, B  A,  var isOpaque = pixel[3] === 255; //    
      
      







次に、任意の便利な方法で、形状識別子と比較できる色をチャネルから取得する必要があります。

イベントメカニズムの実装と識別子の保存と処理の微妙な点については、無数のオプションがあるため、ここでは特に説明しません。



出所



次のリソースがソースとして使用されました。

http://tschaub.net/blog/2011/03/31/canvas-hit-detection.html



この記事は翻訳の権利を主張していませんが、元のリソースのほとんどの資料を使用しています。



All Articles