canvas要素でのマウスクリックの座標を取得するにはどうすればよいですか?


276

(canvas要素に対して)クリックのx座標とy座標を返すcanvas要素にクリックイベントハンドラーを追加する最も簡単な方法は何ですか?

レガシーブラウザの互換性は必要ありません。Safari、Opera、Firefoxがサポートします。


これは、通常のdom要素からマウスイベントを取得することと何ら変わりはありません。quirksmodeそれについての良いリファレンスを持っています。
Airportyh 2008

4
上記のコードは、キャンバスが他のコンテナーの内部にない場合にのみ機能します。一般に、jqueryオフセット関数[var testDiv = $( '#testDiv');のようなものを使用する必要があります。var offset = testDiv.offset();]を使用して、ブラウザ間で正しいオフセットを取得します。これは***の本当の痛みです。
Aaron Watters、2014年

キャンバスを含むページがスクロールする場合、上記のUpdateでポストされたコードは機能しません。
ティモシーキム

質問の更新として含まれていた古い「回答」を削除しました。述べたように、それは時代遅れで不完全でした。
トム

3
ここには50ほどの回答があるため、この男の回答までスクロールすることをお勧めします。パトリック-シンプルで優れた5ライナー。
Igor L. 14

回答:


77

Edit 2018:この回答はかなり古く、現在のすべてのブラウザーでclientXおよびclientYプロパティが機能するため、不要になった古いブラウザーのチェックを使用します。より単純で最近の解決策については、パトリクスアンサーをチェックしてください。

元の回答:
記事に記載されているように、当時は見つかりましたが、存在しません。

var x;
var y;
if (e.pageX || e.pageY) { 
  x = e.pageX;
  y = e.pageY;
}
else { 
  x = e.clientX + document.body.scrollLeft + document.documentElement.scrollLeft; 
  y = e.clientY + document.body.scrollTop + document.documentElement.scrollTop; 
} 
x -= gCanvasElement.offsetLeft;
y -= gCanvasElement.offsetTop;

私にとっては完全にうまくいきました。


30
このソリューションは常に機能するとは限りません。RyanArteconaの回答は、キャンバスが必ずしもページ全体に対して相対的に配置されていない場合のより一般的なケースで機能します。
クリスジョンソン

3
Domアクセスはクリック/移動ごとに行われるため、パフォーマンスが重要な場合、このソリューションは適していません。そしてgetBoundingClientRectが現在存在し、よりエレガントになりました。
GameAlchemist

192

シンプルさが好きでも、ブラウザ間の機能が必要な場合は、このソリューションが最適であることがわかりました。これは、@ Aldekeinのソリューションを単純化したものですが、jQueryはありません

function getCursorPosition(canvas, event) {
    const rect = canvas.getBoundingClientRect()
    const x = event.clientX - rect.left
    const y = event.clientY - rect.top
    console.log("x: " + x + " y: " + y)
}

const canvas = document.querySelector('canvas')
canvas.addEventListener('mousedown', function(e) {
    getCursorPosition(canvas, e)
})

ページが下にスクロールされる場合、ドキュメントのスクロールオフセットも考慮する必要があると思います。
Peppe LG

8
@ PeppeL-G境界クライアントの四角形がそれを計算します。コメントを投稿する前に、コンソールで簡単にテストできます(私がやったことです)。
トマーシュZato -復活モニカ

1
@TomášZato、おお、getBoundingClientRectビューポートに相対的な位置を返しますか?それから私の推測は間違っていました。これは私にとって問題ではなかったので、私はそれをテストしませんでした。また、私が見た潜在的な問題について他の読者に警告したかったのですが、明確にしていただきありがとうございます。
Peppe LG

1
キャンバスがスケーリングされている場合、これは機能しません。それがブラウザのバグかどうかはわかりません。
Jeroen

2
私のような人のための使用法を追加します:var canvas = document.getElementById('canvasID'); canvas.addEventListener("mousedown", function (e) { getCursorPosition(canvas, e);});
SnowOnion

179

更新(5/5/16):シンプルで信頼性が高いため、代わりにパトリックの回答を使用する必要があります。


キャンバスは常にページ全体に相対的にスタイル設定されるわけではないため、canvas.offsetLeft/Top必ずしも必要なものを返すとは限りません。これは、offsetParent要素を基準にしてオフセットされるピクセル数を返します。これはdivposition: relativeスタイルが適用されたキャンバスを含む要素のようなものです。これを説明するにoffsetParentは、canvas要素自体から始めて、s のチェーンをループする必要があります。このコードは、FirefoxとSafariでテストされて完全に機能しますが、すべての環境で機能するはずです。

function relMouseCoords(event){
    var totalOffsetX = 0;
    var totalOffsetY = 0;
    var canvasX = 0;
    var canvasY = 0;
    var currentElement = this;

    do{
        totalOffsetX += currentElement.offsetLeft - currentElement.scrollLeft;
        totalOffsetY += currentElement.offsetTop - currentElement.scrollTop;
    }
    while(currentElement = currentElement.offsetParent)

    canvasX = event.pageX - totalOffsetX;
    canvasY = event.pageY - totalOffsetY;

    return {x:canvasX, y:canvasY}
}
HTMLCanvasElement.prototype.relMouseCoords = relMouseCoords;

最後の行は、キャンバス要素に対するマウス座標を取得するのに便利です。有用な座標を取得するために必要なのは、

coords = canvas.relMouseCoords(event);
canvasX = coords.x;
canvasY = coords.y;

8
いいえ、それは組み込みのJavaScriptのプロトタイプオブジェクト---使用しているdeveloper.mozilla.org/en/...
ガーグ

14
私のChromeには属性event.offsetXevent.offsetY属性があるため、を追加してソリューションを変更しましたif (event.offsetX !== undefined && event.offsetY !== undefined) { return {x:event.offsetX, y:event.offsetY}; }。それは動作するように見えます。
Baczek

3
Baczekは、Chromeの程度正確であるevent.offsetXevent.offsetYもIE9で動作しています。Firefox(v13でテスト済み)の場合event.layerX、およびを使用できますevent.layerY
mafafu 2012

3
私はこれを追加しました: canvasX = event.pageX - totalOffsetX - document.body.scrollLeft; canvasY = event.pageY - totalOffsetY - document.body.scrollTop;
amirpc '29

4
この回答の最終版は私にはうまくいきませんでした。Firefoxでは、画面全体がスクロールされると、変位値が出力として表示されました。stackoverflow.com/a/10816667/578749で提供されている非常によく似た解決策は、event.pageX / Yではなく、event.clientX / Yから計算されたオフセットを差し引いたことです。誰かがこれをレビューして説明できますか?
lvella 2013

33

最新のブラウザがこれを処理します。Chrome、IE9、Firefoxは、offsetX / Yをこのようにサポートし、クリックハンドラーからイベントを渡します。

function getRelativeCoords(event) {
    return { x: event.offsetX, y: event.offsetY };
}

最近のほとんどのブラウザーはlayerX / Yもサポートしていますが、ChromeとIEは、マージン、パディングなどを含むページ上のクリックの絶対オフセットにlayerX / Yを使用しています。Firefoxでは、layerX / YとoffsetX / Yは同等ですが、オフセットは以前は存在しませんでした。そのため、わずかに古いブラウザとの互換性のために、以下を使用できます。

function getRelativeCoords(event) {
    return { x: event.offsetX || event.layerX, y: event.offsetY || event.layerY };
}

1
興味深いことに、layerX、layerYはChromeとFirefoxの両方で定義されていますが、Chromeでは不正確(または別の意味)です。
Julian Mann

@JulianMann情報をありがとう。現在のサポートに基づいて、この回答を更新しました。これで、ほとんど普遍的にoffsetX / Yを使用できるようになりました。
mafafu 2016

18

新しいQuirksmodeによれば、clientXおよびclientYメソッドはすべての主要なブラウザでサポートされています。だから、ここに行きます-スクロールバーのあるページのスクロールdivで機能する優れた機能するコード:

function getCursorPosition(canvas, event) {
var x, y;

canoffset = $(canvas).offset();
x = event.clientX + document.body.scrollLeft + document.documentElement.scrollLeft - Math.floor(canoffset.left);
y = event.clientY + document.body.scrollTop + document.documentElement.scrollTop - Math.floor(canoffset.top) + 1;

return [x,y];
}

これには、jQueryも必要です$(canvas).offset()


@ N4ppeLの回答に相当します。
パヴェルSzczur


11

幅(%)が可変のキャンバスに対するRyan Arteconaの回答を少し変更します。

 HTMLCanvasElement.prototype.relMouseCoords = function (event) {
    var totalOffsetX = 0;
    var totalOffsetY = 0;
    var canvasX = 0;
    var canvasY = 0;
    var currentElement = this;

    do {
        totalOffsetX += currentElement.offsetLeft;
        totalOffsetY += currentElement.offsetTop;
    }
    while (currentElement = currentElement.offsetParent)

    canvasX = event.pageX - totalOffsetX;
    canvasY = event.pageY - totalOffsetY;

    // Fix for variable canvas width
    canvasX = Math.round( canvasX * (this.width / this.offsetWidth) );
    canvasY = Math.round( canvasY * (this.height / this.offsetHeight) );

    return {x:canvasX, y:canvasY}
}

7

座標変換を行うときは注意してください。クリックイベントで複数の非ブラウザ値が返されます。ブラウザーウィンドウがスクロールされている場合(Firefox 3.5およびChrome 3.0で確認済み)、clientXとclientYを単独で使用するだけでは不十分です。

この癖モードの記事は、pageXまたはpageYのいずれか、あるいはclientXとdocument.body.scrollLeftの組み合わせ、およびclientYとdocument.body.scrollTopの組み合わせを使用して、ドキュメントの原点を基準にしたクリック座標を計算できる、より正確な機能を提供します。

更新:さらに、offsetLeftとoffsetTopは、内部サイズではなく、要素のパディングされたサイズを基準にしています。padding:スタイルが適用されたキャンバスは、コンテンツ領域の左上をoffsetLeftとして報告しません。この問題にはさまざまな解決策があります。最も簡単な方法は、キャンバス自体のすべてのボーダー、パディングなどのスタイルをクリアし、代わりにキャンバスを含むボックスに適用することです。


7

親要素ループしてすべての種類の奇妙なことを行うこれらのすべての答えの意味が何であるかわかりません。

このHTMLElement.getBoundingClientRectメソッドは、任意の要素の実際の画面位置を処理するように設計されています。これにはスクロールが含まれるため、次のようなものscrollTopは必要ありません。

(MDNから)外接する四角形を計算するときに、ビューポート領域(またはその他のスクロール可能な要素)で行われたスクロールの量が 考慮されます。

通常の画像

非常に最も簡単な方法は、すでにここに掲載されました。ワイルドなCSSルールが含まれていない限り、これは正しいです。

引き伸ばされたキャンバス/画像の処理

画像のピクセル幅がCSSの幅と一致しない場合は、ピクセル値に比率を適用する必要があります。

/* Returns pixel coordinates according to the pixel that's under the mouse cursor**/
HTMLCanvasElement.prototype.relativeCoords = function(event) {
  var x,y;
  //This is the current screen rectangle of canvas
  var rect = this.getBoundingClientRect();
  var top = rect.top;
  var bottom = rect.bottom;
  var left = rect.left;
  var right = rect.right;
  //Recalculate mouse offsets to relative offsets
  x = event.clientX - left;
  y = event.clientY - top;
  //Also recalculate offsets of canvas is stretched
  var width = right - left;
  //I use this to reduce number of calculations for images that have normal size 
  if(this.width!=width) {
    var height = bottom - top;
    //changes coordinates by ratio
    x = x*(this.width/width);
    y = y*(this.height/height);
  } 
  //Return as an array
  return [x,y];
}

キャンバスに境界線がない限り、それは引き伸ばされた画像(jsFiddle)で機能します。

CSSボーダーの処理

キャンバスの境界線が太い場合、物事は少し複雑になります。文字通り、境界の長方形から境界線を引く必要があります。これは、.getComputedStyleを使用して行うことができます。この回答はプロセスを説明しています

その後、関数は少し大きくなります。

/* Returns pixel coordinates according to the pixel that's under the mouse cursor**/
HTMLCanvasElement.prototype.relativeCoords = function(event) {
  var x,y;
  //This is the current screen rectangle of canvas
  var rect = this.getBoundingClientRect();
  var top = rect.top;
  var bottom = rect.bottom;
  var left = rect.left;
  var right = rect.right;
  //Subtract border size
  // Get computed style
  var styling=getComputedStyle(this,null);
  // Turn the border widths in integers
  var topBorder=parseInt(styling.getPropertyValue('border-top-width'),10);
  var rightBorder=parseInt(styling.getPropertyValue('border-right-width'),10);
  var bottomBorder=parseInt(styling.getPropertyValue('border-bottom-width'),10);
  var leftBorder=parseInt(styling.getPropertyValue('border-left-width'),10);
  //Subtract border from rectangle
  left+=leftBorder;
  right-=rightBorder;
  top+=topBorder;
  bottom-=bottomBorder;
  //Proceed as usual
  ...
}

この最終機能を混乱させるようなことは考えられません。JsFiddleをご覧ください。

ノート

ネイティブprototypeのを変更したくない場合は、関数を変更してそれを呼び出すだけです(canvas, event)(そしていずれかthisをに置き換えますcanvas)。


6

これはとても素敵なチュートリアルです

http://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/

 <canvas id="myCanvas" width="578" height="200"></canvas>
<script>
  function writeMessage(canvas, message) {
    var context = canvas.getContext('2d');
    context.clearRect(0, 0, canvas.width, canvas.height);
    context.font = '18pt Calibri';
    context.fillStyle = 'black';
    context.fillText(message, 10, 25);
  }
  function getMousePos(canvas, evt) {
    var rect = canvas.getBoundingClientRect();
    return {
      x: evt.clientX - rect.left,
      y: evt.clientY - rect.top
    };
  }
  var canvas = document.getElementById('myCanvas');
  var context = canvas.getContext('2d');

  canvas.addEventListener('mousemove', function(evt) {
    var mousePos = getMousePos(canvas, evt);
    var message = 'Mouse position: ' + mousePos.x + ',' + mousePos.y;
    writeMessage(canvas, message);
  }, false);

お役に立てれば!


Ryan Arteconaのソリューションは、ズーム付きのタブレットブラウザーでは機能しませんでした。しかし、これはしました。
アンディマイヤーズ2014

CSS width/ heightオーバーライドされた画像では機能しませんが、それでも最良のソリューションの1つです。
トマーシュ・ザト-モニカを復活させる

3

2016年にjQueryを使用して、キャンバスを基準にしたクリック座標を取得するには、次のようにします。

$(canvas).click(function(jqEvent) {
    var coords = {
        x: jqEvent.pageX - $(canvas).offset().left,
        y: jqEvent.pageY - $(canvas).offset().top
    };
});

これは、キャンバスのoffset()とjqEvent.pageX / Yの両方が、スクロール位置に関係なくドキュメントに対して相対的であるため機能します。

キャンバスがスケーリングされている場合、これらの座標はキャンバスの論理座標と同じではないことに注意してください。それらを取得するには、次のようします。

var logicalCoords = {
    x: coords.x * (canvas.width / $(canvas).width()),
    y: coords.y * (canvas.height / $(canvas).height())
}

ワオ。「jqEvent」はどのように定義されますか?それとも「キャンバス」?または、2番目の例では「coords」ですか?最初の例を2番目の前に実行する必要がありますか?その場合、「それらを入手するために、あなたもそうするだろう」と書いてみませんか?これはすべてonclick関数に含まれますか、それとも何ですか?少しコンテキストを与えて、仲間。そして、元の質問が2008年に尋ねられたことを考えると、2008年に利用可能となったテクノロジーのコンテキストで回答する必要があると思います。当時利用可能だったバージョン(v1.2)から有効なjQueryを使用して回答を絞り込みます。;)
Ayelis

1
わかりました、私の気前のよさでごめんなさい。削除して編集します。最新のフレームワークを使用して回答を提供するつもりでした。そして、プログラマーはjqEvent、canvas、およびcoordsが何であるかを説明する必要がないと思います。
Sarsaparilla

いいね。ご協力ありがとうございます。ごめんなさい、苦労しました!;)
Ayelis

3

したがって、これは単純ですが、見た目よりも少し複雑なトピックです。

まず最初に、ここで混乱した質問があります

  1. 要素の相対マウス座標を取得する方法

  2. 2D Canvas APIまたはWebGLのキャンバスピクセルマウス座標を取得する方法

だから、答えます

要素の相対マウス座標を取得する方法

要素がキャンバスであるかどうかに関係なく、要素の相対的なマウス座標はすべての要素で同じです。

「キャンバスの相対的なマウス座標を取得する方法」という質問に対する2つの簡単な回答があります。

簡単な答え#1の使用offsetXoffsetY

canvas.addEventListner('mousemove', (e) => {
  const x = e.offsetX;
  const y = e.offsetY;
});

この回答はChrome、Firefox、Safariで機能します。他のすべてのイベント値offsetXとは異なり、offsetYCSS変換を考慮に入れます。

2019/05 現在の最大の問題はoffsetXoffsetYタッチイベントには存在しないため、iOS Safariでは使用できません。これらは、ChromeとFirefoxには存在するがSafariには存在しないポインターイベントには存在しますが、Safariが動作しているようです。

別の問題は、イベントがキャンバス自体にある必要があることです。それらを他の要素またはウィンドウに配置した場合、後でキャンバスを参照ポイントとして選択することはできません。

単純な答え#2の使用clientXclientY及びcanvas.getBoundingClientRect

あなたはCSSの変換を気にしない場合は、次の最も簡単な答えは呼び出すことですcanvas. getBoundingClientRect()し、減算から左clientXtopからclientYのように

canvas.addEventListener('mousemove', (e) => {
  const rect = canvas.getBoundingClientRect();
  const x = e.clientX - rect.left;
  const y = e.clientY - rect.top;
});

これは、CSS変換がない限り機能します。タッチイベントでも動作するため、Safari iOSでも動作します

canvas.addEventListener('touchmove', (e) => {
  const rect = canvas. getBoundingClientRect();
  const x = e.touches[0].clientX - rect.left;
  const y = e.touches[0].clientY - rect.top;
});

2D Canvas APIのキャンバスピクセルマウス座標を取得する方法

このために、上記で取得した値を取得し、キャンバスが表示されているサイズからキャンバス自体のピクセル数に変換する必要があります

canvas.getBoundingClientRectclientXclientY

canvas.addEventListener('mousemove', (e) => {
  const rect = canvas.getBoundingClientRect();
  const elementRelativeX = e.clientX - rect.left;
  const elementRelativeY = e.clientY - rect.top;
  const canvasRelativeX = elementRelativeX * canvas.width / rect.width;
  const canvasRelativeY = elementRelativeY * canvas.height / rect.height;
});

またはとoffsetXoffsetY

canvas.addEventListener('mousemove', (e) => {
  const elementRelativeX = e.offsetX;
  const elementRelativeX = e.offsetY;
  const canvasRelativeX = elementRelativeX * canvas.width / canvas.clientWidth;
  const canvasRelativeY = elementRelativeX * canvas.height / canvas.clientHeight;
});

注意: すべての場合において、キャンバスにパディングまたはボーダーを追加しないで。そうすると、コードが非常に複雑になります。代わりに、他の要素でキャンバスを囲むボーダーまたはパディングが必要で、外側の要素にパディングまたはボーダーを追加します。

使用例作業event.offsetXevent.offsetY

canvas.getBoundingClientRectand event.clientXとを使用した作業例event.clientY


2

私はこのリンクをお勧めします-http ://miloq.blogspot.in/2011/05/coordinates-mouse-click-canvas.html

<style type="text/css">

  #canvas{background-color: #000;}

</style>

<script type="text/javascript">

  document.addEventListener("DOMContentLoaded", init, false);

  function init()
  {
    var canvas = document.getElementById("canvas");
    canvas.addEventListener("mousedown", getPosition, false);
  }

  function getPosition(event)
  {
    var x = new Number();
    var y = new Number();
    var canvas = document.getElementById("canvas");

    if (event.x != undefined && event.y != undefined)
    {
      x = event.x;
      y = event.y;
    }
    else // Firefox method to get the position
    {
      x = event.clientX + document.body.scrollLeft +
          document.documentElement.scrollLeft;
      y = event.clientY + document.body.scrollTop +
          document.documentElement.scrollTop;
    }

    x -= canvas.offsetLeft;
    y -= canvas.offsetTop;

    alert("x: " + x + "  y: " + y);
  }

</script>

のポイントはx = new Number()何ですか?再割り当てする以下のコードxは、割り当てられた数値がただちに破棄されることを意味します
gman


1

あなたはただ行うことができます:

var canvas = yourCanvasElement;
var mouseX = (event.clientX - (canvas.offsetLeft - canvas.scrollLeft)) - 2;
var mouseY = (event.clientY - (canvas.offsetTop - canvas.scrollTop)) - 2;

これにより、マウスポインターの正確な位置がわかります。


1

http://jsbin.com/ApuJOSA/1/edit?html,outputにあるデモを参照してください。

  function mousePositionOnCanvas(e) {
      var el=e.target, c=el;
      var scaleX = c.width/c.offsetWidth || 1;
      var scaleY = c.height/c.offsetHeight || 1;

      if (!isNaN(e.offsetX)) 
          return { x:e.offsetX*scaleX, y:e.offsetY*scaleY };

      var x=e.pageX, y=e.pageY;
      do {
        x -= el.offsetLeft;
        y -= el.offsetTop;
        el = el.offsetParent;
      } while (el);
      return { x: x*scaleX, y: y*scaleY };
  }

0

上記のRyan Arteconaのソリューションのいくつかの変更を次に示します。

function myGetPxStyle(e,p)
{
    var r=window.getComputedStyle?window.getComputedStyle(e,null)[p]:"";
    return parseFloat(r);
}

function myGetClick=function(ev)
{
    // {x:ev.layerX,y:ev.layerY} doesn't work when zooming with mac chrome 27
    // {x:ev.clientX,y:ev.clientY} not supported by mac firefox 21
    // document.body.scrollLeft and document.body.scrollTop seem required when scrolling on iPad
    // html is not an offsetParent of body but can have non null offsetX or offsetY (case of wordpress 3.5.1 admin pages for instance)
    // html.offsetX and html.offsetY don't work with mac firefox 21

    var offsetX=0,offsetY=0,e=this,x,y;
    var htmls=document.getElementsByTagName("html"),html=(htmls?htmls[0]:0);

    do
    {
        offsetX+=e.offsetLeft-e.scrollLeft;
        offsetY+=e.offsetTop-e.scrollTop;
    } while (e=e.offsetParent);

    if (html)
    {
        offsetX+=myGetPxStyle(html,"marginLeft");
        offsetY+=myGetPxStyle(html,"marginTop");
    }

    x=ev.pageX-offsetX-document.body.scrollLeft;
    y=ev.pageY-offsetY-document.body.scrollTop;
    return {x:x,y:y};
}

0

まず、他の人が言ったように、キャンバス要素の位置を取得する関数が必要です。これは、このページの他のいくつか(IMHO)よりも少しエレガントな方法です。任意の要素を渡して、ドキュメント内での位置を取得できます。

function findPos(obj) {
    var curleft = 0, curtop = 0;
    if (obj.offsetParent) {
        do {
            curleft += obj.offsetLeft;
            curtop += obj.offsetTop;
        } while (obj = obj.offsetParent);
        return { x: curleft, y: curtop };
    }
    return undefined;
}

次に、それに対するカーソルの現在の位置を計算します。

$('#canvas').mousemove(function(e) {
    var pos = findPos(this);
    var x = e.pageX - pos.x;
    var y = e.pageY - pos.y;
    var coordinateDisplay = "x=" + x + ", y=" + y;
    writeCoordinateDisplay(coordinateDisplay);
});

ジェネリックfindPos関数をイベント処理コードから分離したことに注意してください。(あるべきように。関数をそれぞれ1つのタスクに留めるようにしてください。)

offsetLeftとはoffsetTop相対にあるoffsetParentいくつかのラッパー可能性があり、div(そのことについてまたは何か、)ノード。要素をラップする要素がない場合、canvasそれらはに相対的であるため、body減算するオフセットはありません。これが、他の作業を行う前にキャンバスの位置を決定する必要がある理由です。

Similaryは、e.pageXおよびe.pageYドキュメントにカーソルの位置を与えます。そのため、これらの値からキャンバスのオフセットを差し引いて、実際の位置に到達します。

配置された要素の代替方法は、e.layerXおよびの値を直接使用することですe.layerY。次の2つの理由により、これは上記の方法よりも信頼性が低くなります。

  1. これらの値は、配置された要素内でイベントが発生しない場合のドキュメント全体にも関連します。
  2. それらは標準の一部ではありません

0

ThreeJS r77

var x = event.offsetX == undefined ? event.layerX : event.offsetX;
var y = event.offsetY == undefined ? event.layerY : event.offsetY;

mouse2D.x = ( x / renderer.domElement.width ) * 2 - 1;
mouse2D.y = - ( y / renderer.domElement.height ) * 2 + 1;

多くの解決策を試した後。これでうまくいきました。他の誰かを助けて投稿するかもしれません。ここから手に入れまし


0

ここに簡略化されたソリューションがあります(これは境界線/スクロールでは機能しません):

function click(event) {
    const bound = event.target.getBoundingClientRect();

    const xMult = bound.width / can.width;
    const yMult = bound.height / can.height;

    return {
        x: Math.floor(event.offsetX / xMult),
        y: Math.floor(event.offsetY / yMult),
    };
}

0

私はpdfの上にキャンバスを持つアプリケーションを作成していました。これには、pdfのズームインとズームアウトなど、キャンバスの多くのサイズ変更が含まれます。次に、PDFのズームイン/アウトごとに、キャンバスをサイズ変更して、 PDFのサイズ、私はstackOverflowで多くの答えを調べましたが、最終的に問題を解決する完璧な解決策を見つけられませんでした。

私はrxjsとangular 6 を使用していて、最新バージョンに固有の答えは見つかりませんでした。

これは、rxjsを利用してキャンバスの上に描画するのに役立つコードスニペット全体です。

  private captureEvents(canvasEl: HTMLCanvasElement) {

    this.drawingSubscription = fromEvent(canvasEl, 'mousedown')
      .pipe(
        switchMap((e: any) => {

          return fromEvent(canvasEl, 'mousemove')
            .pipe(
              takeUntil(fromEvent(canvasEl, 'mouseup').do((event: WheelEvent) => {
                const prevPos = {
                  x: null,
                  y: null
                };
              })),

              takeUntil(fromEvent(canvasEl, 'mouseleave')),
              pairwise()
            )
        })
      )
      .subscribe((res: [MouseEvent, MouseEvent]) => {
        const rect = this.cx.canvas.getBoundingClientRect();
        const prevPos = {
          x: Math.floor( ( res[0].clientX - rect.left ) / ( rect.right - rect.left ) * this.cx.canvas.width ),
          y:  Math.floor( ( res[0].clientY - rect.top ) / ( rect.bottom - rect.top ) * this.cx.canvas.height )
        };
        const currentPos = {
          x: Math.floor( ( res[1].clientX - rect.left ) / ( rect.right - rect.left ) * this.cx.canvas.width ),
          y: Math.floor( ( res[1].clientY - rect.top ) / ( rect.bottom - rect.top ) * this.cx.canvas.height )
        };

        this.coordinatesArray[this.file.current_slide - 1].push(prevPos);
        this.drawOnCanvas(prevPos, currentPos);
      });
  }

そして、これが修正するスニペットです。キャンバスのズームイン/ズームアウトの方法に関係なく、キャンバスのサイズを基準にしたマウス座標です。

const prevPos = {
  x: Math.floor( ( res[0].clientX - rect.left ) / ( rect.right - rect.left ) * this.cx.canvas.width ),
  y:  Math.floor( ( res[0].clientY - rect.top ) / ( rect.bottom - rect.top ) * this.cx.canvas.height )
};
const currentPos = {
  x: Math.floor( ( res[1].clientX - rect.left ) / ( rect.right - rect.left ) * this.cx.canvas.width ),
  y: Math.floor( ( res[1].clientY - rect.top ) / ( rect.bottom - rect.top ) * this.cx.canvas.height )
};

-1

ねえ、これは道場にあります、それは私がすでにプロジェクトのコードを持っているものだからです。

それを非dojoバニラJavaScriptに変換する方法はかなり明白なはずです。

  function onMouseClick(e) {
      var x = e.clientX;
      var y = e.clientY;
  }
  var canvas = dojo.byId(canvasId);
  dojo.connect(canvas,"click",onMouseClick);

お役に立てば幸いです。


6
clientX / clientYは、ブラウザ間で同様に動作しません。
tfwright
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.