真正的鼠标在canvas上的位置

我试图用鼠标在HTML5canvas上绘制,但是看起来效果不错的唯一方法是如果canvas位于位置0,0(左上angular),如果我更改canvas位置,出于某种原因它并不像它应该画的那样。 这是我的代码。

function createImageOnCanvas(imageId){ document.getElementById("imgCanvas").style.display = "block"; document.getElementById("images").style.overflowY= "hidden"; var canvas = document.getElementById("imgCanvas"); var context = canvas.getContext("2d"); var img = new Image(300,300); img.src = document.getElementById(imageId).src; context.drawImage(img, (0),(0)); } function draw(e){ var canvas = document.getElementById("imgCanvas"); var context = canvas.getContext("2d"); posx = e.clientX; posy = e.clientY; context.fillStyle = "#000000"; context.fillRect (posx, posy, 4, 4); } 

HTML部分

  <body> <div id="images"> </div> <canvas onmousemove="draw(event)" style="margin:0;padding:0;" id="imgCanvas" class="canvasView" width="250" height="250"></canvas> 

我读过有一种在JavaScript中创build简单函数的方法来获得正确的位置,但我不知道如何去做。

简单的1:1情景

对于canvas元素与位图大小相比为1:1的情况,可以使用以下片段获取鼠标位置:

 function getMousePos(canvas, evt) { var rect = canvas.getBoundingClientRect(); return { x: evt.clientX - rect.left, y: evt.clientY - rect.top }; } 

只要将事件和canvas作为参数从事件中调用即可。 它返回一个x和y的鼠标位置的对象。

由于鼠标位置相对于客户端窗口,您必须减去canvas元素的位置才能将其转换为相对于元素本身的位置。

在你的代码中集成的例子:

 //put this outside the event loop.. var canvas = document.getElementById("imgCanvas"); var context = canvas.getContext("2d"); function draw(evt) { var pos = getMousePos(canvas, evt); context.fillStyle = "#000000"; context.fillRect (pos.x, pos.y, 4, 4); } 

修改

注意:如果直接应用于canvas元素,则边界和填充将影响位置,因此需要通过getComputedStyle()来考虑这些位置,或者将这些样式应用于父div。

元素和位图的大小不同时

当存在元素大小不同于位图本身的情况时,例如,使用CSS缩放元素或者存在像素高宽比等,则必须解决这个问题。

例:

 function getMousePos(canvas, evt) { var rect = canvas.getBoundingClientRect(), // abs. size of element scaleX = canvas.width / rect.width, // relationship bitmap vs. element for X scaleY = canvas.height / rect.height; // relationship bitmap vs. element for Y return { x: (evt.clientX - rect.left) * scaleX, // scale mouse coordinates after they have y: (evt.clientY - rect.top) * scaleY // been adjusted to be relative to element } } 

小提琴使用规模

随着转换适用于上下文(规模,旋转等)

那么就有更复杂的情况,例如旋转,倾斜/剪切,缩放,平移等对上下文进行了转换。要处理这个问题,可以计算当前matrix的逆matrix。

较新的浏览器可以通过currentTransform属性和Firefox(当前alpha)读取当前matrix,甚至可以通过mozCurrentTransformInverted提供一个反转matrix。 Firefox然而,通过mozCurrentTransform ,将返回一个数组而不是DOMMatrix因为它应该。 Chrome通过实验性标志启用后,将返回一个DOMMatrix而不是SVGMatrix

但是在大多数情况下,您必须实现自己的自定义matrix解决scheme(例如我自己的解决scheme – 免费/ MIT项目),直到获得全面支持。

当你最终获得了matrix,而不pipe你获得一个matrix,你需要反转它并将其应用到你的鼠标坐标。 然后将坐标传递给canvas,该canvas将使用其matrix将其转换回到目前的位置。

这样的话,这个点就会相对于鼠标处于正确的位置。 在这里你也需要调整坐标(在应用逆matrix之前)以相对于元素。

一个只是显示matrix步骤的例子

 function draw(evt) { var pos = getMousePos(canvas, evt); // get adjusted coordinates as above var imatrix = matrix.inverse(); // get inverted matrix somehow pos = imatrix.applyToPoint(pos.x, pos.y); // apply to adjusted coordinate context.fillStyle = "#000000"; context.fillRect(pos.x-1, pos.y-1, 2, 2); } 

使用上面链接的解决scheme的示例 (更广泛支持时,replace为本地浏览器解决scheme)。

在执行时使用currentTransform一个例子是:

  var pos = getMousePos(canvas, e); // get adjusted coordinates as above var matrix = ctx.currentTransform; // W3C (future) var imatrix = matrix.invertSelf(); // invert // apply to point: var x = pos.x * imatrix.a + pos.y * imatrix.c + imatrix.e; var y = pos.x * imatrix.b + pos.y * imatrix.d + imatrix.f; 

更新我提出了一个免费的解决scheme(MIT),将所有这些步骤embedded到一个易于使用的对象中,这个对象可以在这里find,也可以处理其他几个最不理会的事情。

您可以使用以下代码获取鼠标位置:

 function getMousePos(canvas, evt) { var rect = canvas.getBoundingClientRect(); return { x: (evt.clientX - rect.left) / (rect.right - rect.left) * canvas.width, y: (evt.clientY - rect.top) / (rect.bottom - rect.top) * canvas.height }; } 

这段代码考虑了当canvas尺寸和样式尺寸不同时,canvas坐标( evt.clientX - rect.left )的变化坐标和缩放比例/ (rect.right - rect.left) * canvas.width : Canvas width和HTML5中的高度 )。

例如: http : //jsfiddle.net/sierawski/4xezb7nL/

来源:jerryj评论http://www.html5canvastutorials.com/advanced/html5-canvas-mouse-coordinates/

您需要获取相对于canvas的鼠标位置

为此,您需要知道页面上canvas的X / Y位置。

这被称为canvas的“偏移量”,这里是如何获得偏移量。 (为了简化跨浏览器的兼容性,我使用了jQuery,但是如果你想使用原始的javascript,谷歌也可以使用它)。

  var canvasOffset=$("#canvas").offset(); var offsetX=canvasOffset.left; var offsetY=canvasOffset.top; 

然后在鼠标处理程序中,可以像这样获取鼠标X / Y:

  function handleMouseDown(e){ mouseX=parseInt(e.clientX-offsetX); mouseY=parseInt(e.clientY-offsetY); } 

下面是一个演示代码和小提琴,演示如何在canvas上成功跟踪鼠标事件:

http://jsfiddle.net/m1erickson/WB7Zu/

 <!doctype html> <html> <head> <link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css --> <script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script> <style> body{ background-color: ivory; } canvas{border:1px solid red;} </style> <script> $(function(){ var canvas=document.getElementById("canvas"); var ctx=canvas.getContext("2d"); var canvasOffset=$("#canvas").offset(); var offsetX=canvasOffset.left; var offsetY=canvasOffset.top; function handleMouseDown(e){ mouseX=parseInt(e.clientX-offsetX); mouseY=parseInt(e.clientY-offsetY); $("#downlog").html("Down: "+ mouseX + " / " + mouseY); // Put your mousedown stuff here } function handleMouseUp(e){ mouseX=parseInt(e.clientX-offsetX); mouseY=parseInt(e.clientY-offsetY); $("#uplog").html("Up: "+ mouseX + " / " + mouseY); // Put your mouseup stuff here } function handleMouseOut(e){ mouseX=parseInt(e.clientX-offsetX); mouseY=parseInt(e.clientY-offsetY); $("#outlog").html("Out: "+ mouseX + " / " + mouseY); // Put your mouseOut stuff here } function handleMouseMove(e){ mouseX=parseInt(e.clientX-offsetX); mouseY=parseInt(e.clientY-offsetY); $("#movelog").html("Move: "+ mouseX + " / " + mouseY); // Put your mousemove stuff here } $("#canvas").mousedown(function(e){handleMouseDown(e);}); $("#canvas").mousemove(function(e){handleMouseMove(e);}); $("#canvas").mouseup(function(e){handleMouseUp(e);}); $("#canvas").mouseout(function(e){handleMouseOut(e);}); }); // end $(function(){}); </script> </head> <body> <p>Move, press and release the mouse</p> <p id="downlog">Down</p> <p id="movelog">Move</p> <p id="uplog">Up</p> <p id="outlog">Out</p> <canvas id="canvas" width=300 height=300></canvas> </body> </html> 

引用这个问题: 我得到的mouseEvent.offsetX比实际的canvas大小要大得多 。我已经给出了一个函数,它将完全适合你的情况

你不需要JavaScript。 设置position:relative; 在你的CSS的canvas元素。 比运行一个脚本来不断修正坐标要简单得多。