一、PC PC是通過滑鼠點擊和移動,相對比較簡單,比如onmousedown、onmouseup、onmousemove、onmouseout滑鼠按鍵按下、按鍵起來、滑鼠在元素上移動、滑鼠從元素上離開。 PC端可以直接通過事件的clientX和clientY來獲取點擊的坐標,這個坐標(e.clien ...
一、PC
PC是通過滑鼠點擊和移動,相對比較簡單,比如onmousedown、onmouseup、onmousemove、onmouseout滑鼠按鍵按下、按鍵起來、滑鼠在元素上移動、滑鼠從元素上離開。
canvas.onmousedown = function(e) { console.log(e.clientX, e.clientY); } canvas.onmouseup = function(e) { console.log(e.clientX, e.clientY); } canvas.onmousemove = function(e) { console.log(e.clientX, e.clientY); } canvas.onmouseout = function(e) { console.log(e.clientX, e.clientY); }
PC端可以直接通過事件的clientX和clientY來獲取點擊的坐標,這個坐標(e.clientX , e.clientY)是相對於window的左上角來確定的。
同樣事件參數evnet,有一些常用方法如阻止事件在瀏覽器中的預設操作和事件冒泡。
e.preventDefault()為阻止事件在瀏覽器中的預設操作,如input type為submit時的提交操作,我一般在事件函數中都會使用它,特別是在移動端。記得之前有個坑,在微信內置瀏覽器中,touchmove事件觸發時,微信內置瀏覽器會預設拖動整個WebView向上或向下移動,顯示出那個QQ瀏覽器內核什麼鬼的文字,而沒有執行想要的操作。
e.stopPropagation()為防止事件穿透,不調用此方法時,事件被捕獲後,仍然會繼續傳播可能會被下方的元素事件所捕獲進而造成影響。所以在元素覆蓋元素,且都有綁定事件的時候需要阻止事件冒泡。
二、移動
移動和PC在處理事件上有些不同之處,首先事件上不同,移動這邊是touchstart、touchmove、touchend這3個事件。
canvas.addEventListener("touchstart", function(e) { console.log(e.touches[0].pageX, e.touches[0].pageY); }); canvas.addEventListener("touchmove", function(e) { if(e.touches.length > 1 || e.scale && e.scale !== 1) return; console.log(e.touches[0].pageX, e.touches[0].pageY); }); canvas.addEventListener("touchend", function(e) {});
移動端由於是手指操作而非滑鼠,所以存在多點觸控,即多根手指在屏幕上觸發事件。所以,不在跟PC一樣,通過e.clientX來獲取單個點坐標。而是事件event中存在一個觸控集合touches這個數組,通過取數組的第一個元素來獲取坐標位置,即第一個觸碰屏幕手指的坐標(e.touches[0].pageX , e.touches[0].pageY)。而有時往往有需要獲取全部觸碰點的位置,那就要迴圈數組了,逐個處理。另一個坑就是有時要防止多點觸碰,以及手指對屏幕進行縮放的影響,可以加入以上判斷if(e.touches.length > 1 || e.scale && e.scale != 1)。
最後就是touchend事件,代表手指離開屏幕不存在觸控,所以e.touches這個數組的長度為0,也就不能在touchend的處理函數中獲取pageX屬性了。
三、元素內的位置
通過以上方法獲取的坐標是以window左上角為原點的坐標,但是在實際中,往往獲取的是以某個元素左上角為原點的坐標,這時就需要做個轉化。以canvas為例
function windowToCanvas(x, y) { //window坐標轉canvas坐標 return { x: Math.round(x - document.getElementById("canvas").getBoundingClientRect().left), y: Math.round(y - document.getElementById("canvas").getBoundingClientRect().top) } }
getBoundingClientRect()方法可以獲取元素的盒子模型,通過top、left、right、bottom這4個屬性可以拿到四周的邊距。