獲取鼠標在 canvas 中的位置


 

一般情況

一般情況下,如果需要在 canvas 中獲取鼠標指針坐標,可以通過監聽鼠標的 mousemove(如果只需單擊時的坐標,可以用 click)事件。 當事件被觸發時,我們可以獲取鼠標相對於 viewport 的坐標(event.clientXevent.clientY)。 同時,我們可以通過 canvas.getBoundingClientRect() 來獲取 canvas 相對於 viewport 的坐標,這樣我們就可以計算出鼠標在 canvas 中的坐標。

canvas.addEventListener("click", function __handler__(evt) { var x = evt.clientX; var y = evt.clientY; var rect = canvas.getBoundingClientRect(); x -= rect.left; y -= rect.top; console.log(x, y); // (x, y) 就是鼠標在 canvas 單擊時的坐標 });

** DEMO-1 **

設置了 border/padding

一般情況下,我們根據上面的方法獲取出來的坐標是准確的,但當我們在 canvas 上添加了 border 或 padding 后,坐標就出現了偏移。

** DEMO-2-0 **

這是因為在 canvas 中,坐標區域是 canvas 元素的 content 區域,不包括 border 和 padding,而通過上面得到的坐標原點在 canvas 的 border 開始的。因此,這里還需要減去 border 和 padding。

var style = window.getComputedStyle(canvas, null); var borderLeft = parseFloat(style["border-left-width"]); var borderTop = parseFloat(style["border-top-width"]); var paddingLeft = parseFloat(style["padding-left"]); var paddingTop = parseFloat(style["padding-top"]); canvas.addEventListener("click", function __handler__(evt) { var x = evt.clientX; var y = evt.clientY; var rect = canvas.getBoundingClientRect(); x -= rect.left - borderLeft - paddingLeft; // 去除 borderLeft paddingLeft 后的坐標 y -= rect.top - borderTop - paddingTop; // 去除 borderLeft paddingLeft 后的坐標 console.log(x, y); // (x, y) 就是鼠標在 canvas 單擊時的坐標 });

** DEMO-2-1 **

設置了 css width/height

當在 canvas 上設置了 css 的 width、height,並且與 canvas 的 width、height 屬性不同時(可以非常簡單對 canvas 進行放大或縮小,在移動頁面上常常會使用)。從上面計算出來的坐標在 canvas 里使用又會出現偏移。

** DEMO-3-0 **

這里就需要對坐標進行修正:

var style = window.getComputedStyle(canvas, null); var cssWidth = parseFloat(style["width"]); var cssHeight = parseFloat(style["height"]); var scaleX = canvas.width / cssWidth; // 水平方向的縮放因子 var scaleY = canvas.height / cssHeight; // 垂直方向的縮放因子 canvas.addEventListener("click", function __handler__(evt) { var x = evt.clientX; var y = evt.clientY; var rect = canvas.getBoundingClientRect(); x -= rect.left; y -= rect.top; x *= scaleX; // 修正水平方向的坐標 y *= scaleY; // 修正垂直方向的坐標 console.log(x, y); // (x, y) canvas 里的坐標 });

** DEMO-3-1 **

設置了 transform

如果我們在 canvas 的 style 上添加了 transform,又有可能會導致上面計算出來的坐標出現偏移。

** DEMO-4-0 **

而且經過 transform 后很難通過已經的 API 來計算出准確的坐標?w3c 為了解決這個問題,在 CSSOM-View 中添加了一個名為 GeometryUtils 的接口,該接口提供了一系列的 api 幫助我們對頁面上的點、矩形、四邊形等的坐標進行轉換(目前只有 Firefox 支持)。 這里我們使用其中的 convertPointFromNode 方法,直接把在 viewport 的坐標 (evt.clientX, evt.clientY) 轉換成相對於 canvas 元素的坐標。 如果 canvas 同時設置了樣式 width、height、box-sizing,我們可以使用 getBoxQuads 方法來獲取 canvas 經過 transform 之前的元素的 width 和 height(雖然可以使用通過獲取 style 的相關屬性來計算,但這種方式太麻煩了)來計算出經過 css 縮放的因子。

var quads = canvas.getBoxQuads({ box: "content", relativeTo: canvas }); var bounds = quads[0]; var scaleX = canvas.width / bounds.width; var scaleY = canvas.height / bounds.height; canvas.addEventListener("click", function __handler__(evt) { var {x, y} = canvas.convertPointFromNode({ x: evt.clientX, y: evt.clientY }, document, { toBox: "content" }); x *= scaleX; y *= scaleY; console.log(x, y); });

** DEMO-4-1 **

在文章的最后,貼上另一種方法的解決方案:

** DEMO-4-2 **


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM