2
  1. キャンバスがベクトルのビットマップを描画しているため(ビットマップはパスではないため)、これは機能しないと思います。
  2. それが機能したとしても、ビットマップには常に長方形の許可があります。

isPointInPath使用するときのようなものを活用する方法はありますdrawImageか?

例:

  • 上部のキャンバスはを使用して描画されdrawImageisPointInPath機能しません。
  • 下部のキャンバスはを使用arcして描画され、isPointInPath機能します。

私の証明へのリンク

** 編集 **

1つのキャンバスに円を描き、isPointInPathマウスポインタが円の内側にあるかどうかを確認するために使用します(この例では下のキャンバス)。また、を使用して下部のキャンバスを上部のキャンバスに「コピー」しますdrawImage。上部のキャンバスでは機能しないことに注意してくださいisPointInPath(おそらく上記の理由による)。あらゆる種類のパス(またはビットマップ)で機能する回避策はありますか?

4

4 に答える 4

4

キャンバスコンテキストには、現在のパスと呼ばれるこの隠されたものがあります。ctx.beginPathctx.lineToなどがこのパスを作成します。

電話をかけるctx.stroke()ctx.fill()、キャンバスがそのパスをストロークまたは塗りつぶすとき。

ストロークまたは塗りつぶされた後でも、パスはコンテキストに存在します。

テストするのはこのパスだけです。isPointInPath

描画した画像またはで描画された長方形に何かが含まれているかどうかをテストする場合は、ctx.fillRect()組み込みのメソッドを使用してテストすることはできません。

通常、自分で作成した(または他の人から取得した)is-point-in-rectangle関数を使用する必要があります。

画像の(画像の長方形だけでなく)ピクセルパーフェクトなヒット検出を行う方法を探している場合は、ここで説明するさまざまな方法があります。Canvasを使用したピクセルパーフェクトな2Dマウスピッキング

于 2011-12-24T00:22:34.433 に答える
1

ctx.drawImage()次のように、画像自体の後ろに常にボックスを描画するように再実装してみることができます( JSFiddleの例)。

ctx.customDrawImage = function(image, x, y){
    this.drawImage(image, x, y);
    this.rect(x, y, image.width, image.height);
}
var img1 = new Image();
img1.onload = function(){
var x = y = 0;
ctx.drawImage(img1, x, y);
console.log(ctx.isPointInPath(x + 1, y + 1));

x = 1.25 * img1.width;
ctx.customDrawImage(img1, x, y);
console.log(ctx.isPointInPath(x + 1, y + 1));

注:注意しないと、画像の上に長方形が表示されたり、後ろからにじんだりするなどの副作用が発生する可能性があります。

于 2011-12-24T00:33:00.570 に答える
0

私にとって、キャンバスを移動した後、isPointInPathが失敗しました。だから、私は使用しました:

mouseClientX -= gCanvasElement.offsetLeft; mouseclientY -= gCanvasElement.offsetTop;

于 2017-05-07T05:13:22.733 に答える
0

キャンバス要素を再スケーリングできるため、さらにいくつかの課題がありました。したがって、最初に図形を描画するとき、私の場合は円弧で、名前と一緒に配列に保存して描画します。

      if (this.coInit == false)
      {
        let co = new TempCO ();
        co.name= sensor.Name;
        co.path = new Path2D();
        co.path.arc(c.X, c.Y, this.radius,  0, 2 * Math.PI);
        this.coWithPath.push(co);
      }
      let coWP = this.coWithPath.find(c=>c.name == sensor.Name);
      this.ctx.fillStyle = color;
      this.ctx.fill(coWP.path);

次に、マウスイベントでアイテムをループし、クリックイベントがパス内にあるかどうかを確認します。ただし、サイズ変更されたキャンバスに応じてマウス座標を再スケーリングする必要もあります。

getCursorPosition(event) {
  const rect = this.ctx.canvas.getBoundingClientRect();
  const x = ((event.clientX - rect.left ) / rect.width) * this.canvasWidth;
  const y = ((event.clientY - rect.top) / rect.height) * this.canvasHeight;
  this.coWithPath.forEach(c=>{

    if (this.ctx.isPointInPath(c.path, x, y))
    {
      console.log("arc is hit", c);
      //Switch light
    }
  });
}

そこで、キャンバスの現在のサイズを取得し、ポイントを元のサイズに再スケーリングします。今それは動作します!

TempCOは次のようになります。

export class TempCO
{
  path : Path2D;
  name : string;
}
于 2020-06-15T14:05:49.487 に答える