2016-11-30 52 views
1

我正在嘗試使用HTML5 canvas元素。我想要做的一件事是設置一個mousemove事件來追蹤畫布上的鼠標以進行繪圖和其他目的。我一直無法找到關於如何獲得鼠標所在畫布中像素的精確座標的明確答案。我發現了這個網站在網絡上的教程(我加了背景顏色的畫布,使其在呈現的頁面上明顯):在Javascript中,爲什麼getBoundingClientRect()有時會返回浮點值?

<!DOCTYPE HTML> 
<html> 
    <head> 
    <style> 
     body { 
     margin: 0px; 
     padding: 0px; 
     } 

     #myCanvas { 
     background-color: cornflowerblue; 
     } 
    </style> 
    </head> 
    <body> 
    <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); 
    </script> 
    </body> 
</html> 

當加載頁面時,你看到的畫布作爲頁面左上角的藍色矩形。將鼠標移到它上面,畫布上的文字變爲鼠標位置,顯示爲兩個整數,X和Y各一個。

然後我通過添加頂部和左側邊距來修改畫布樣式,並將其餘部分的頁面不變。

#myCanvas { 
    background-color: cornflowerblue; 
    margin-left: 30px; 
    margin-top: 30px; 
} 

當我現在渲染頁面時,畫布的藍色矩形已從頁面的頂部和左側偏移,如我所料。但是將鼠標移到畫布上時,畫布中顯示的X和Y鼠標座標將以浮點形式顯示,並顯示許多小數位。通過代碼跟蹤一下,看起來getBoundingClientRect()返回一個矩形,其值左上和右上都是浮點數。

我假設我可以做一些像截斷或舍入getBoundingClientRect()所返回的值的東西,但這感覺就像是對我而言的錯誤方式。

我在某種程度上使用getBoundingClientRect()不正確,或者它是否應該返回浮點值?

是否有一個明確的方法來獲取鼠標在畫布上的確切的X和Y座標,當聽各種鼠標事件?

回答

3

tldr;您在瀏覽器中進行了縮放/取消縮放。

問題

margin-left: 30px; 

在這種jsfiddle這就是模仿你的問題是不一樣,你在我的電腦上說,當導航變焦設置爲100%(正常)的作品。但是,如果你放大瀏覽器,你會注意到這種行爲。

margin-left: 11%; 

相反,如果你在這個jsfiddle使用%的保證金一樣,你會發現它的回報浮動鼠標位置羯羊變焦爲開。

答案

的事情是因爲它出現在屏幕上鼠標位置的計算:它可能只因爲它是基於像素的整個位置座標。

但是,在應用邊距,縮放和其他修改器之後,但在告訴GPU呈現它之前,getBoundingClientRect返回瀏覽器計算的「元素的邊界客戶端矩形」。簡而言之,它會返回元素的實際位置,稍後由GPU進行近似以在像素矩陣內進行渲染。如果您使用像素邊距/大小/填充/等等,那麼元素位置保持基於整數,但是如果您放大或使用em /%定位值,則可能會導致浮動位置。

的解決方案

  1. 輪邊界
  2. 假設這確實是一個浮動的位置,它只是需要詳談,以使其適合在屏幕上的GPU

編輯:被遺忘的解決方案

+0

正在看這個問題 - 很好的答案。 – VSO

+0

我正試圖消化你的答案。但從你的解決方案,以及我的觀察,getBoundingClientRect()並不總是返回一個「幾乎四捨五入」的浮點數,我有這個問題:如果我想用canvas元素來編程一個遊戲,我是否有權假設沒有辦法進行涉及鼠標的像素精確碰撞檢測以及畫布上繪製的內容? – vfs23

+0

我認爲你是對的,因爲你提到的原因(如果你的畫布的CSS大小發生變化,而不是它的js大小,那麼你甚至會在以後出現其他問題,因爲在畫布上很難保留基於像素的元素)。 –

相關問題