這段時間研究canvas,在交互這里遇到了比較大的坑。
據我目前所知,canvas納入標准的常用交互接口(可能也就這一個)是 isPointInPath() ,它可以判斷js設置的事件條件是否處於當前繪圖路徑中,或者說最后一個路徑,具體使用如下
1 //獲取鼠標指針坐標 2 function getMousePos(evt) { 3 var rect = document.getElementById('canvas').getBoundingClientRect(); 4 return { 5 x: evt.clientX - rect.left, 6 y: evt.clientY - rect.top 7 }; 8 } 9 10 document.getElementById(selector).addEventListener('click', function (evt) { 11 var mousePos = getMousePos(evt); 12 if (context.isPointInPath(mousePos.x, mousePos.y)) { 13 //重繪 14 } 15 }, false);
由於canvas不保存繪圖路徑,繪完了就bia在頁面上,成死的了,因此無法對最后一條路徑之前的路徑重新拿出來處理。那么傳統方法如何處理?--重繪,再針對每一個繪圖路徑使用 isPointInPath() 判斷,核心代碼使用如下(來自腳兒網,謝謝作者)
1 ... 2 function draw () { 3 ... 4 } 5 function circle () { 6 ... 7 } 8 9 draw(); 10 ctx.fill() 11 circle(); 12 ctx.fill() 13 14 var fns = [draw,circle]; 15 cvs.onmousemove = function (e) { 16 var x = e.offsetX, y = e.offsetY; 17 ctx.clearRect(0,0,400,300) 18 for(var i = fns.length;i--;) { 19 fns[i](); 20 if(ctx.isPointInPath(x,y)) { 21 ctx.fillStyle = "#f00" 22 } else { 23 ctx.fillStyle = "#000" 24 } 25 ctx.fill() 26 } 27 }
canvas只有一張畫布,對之前任何一個路徑作刷新,需要重繪所有受到影響的路徑,因此,當需要重繪的動作越來越多時,就會對性能造成極大考驗。作為HTML5的新寵兒,不應就此中道崩殂,我們也不想寫如上略顯累贅的代碼。今天在查閱資料后,發現一個尚在討論的新接口 addHitRegion() MDN,使用簡單而且可以實現良好的交互效果,目前在chrome和firefox下測試可用(需要在chrome://flags中啟用【實驗性畫布功能】或在firefox中輸入about:config使canvas.hitregions.enabled值為true)
具體使用如下
繪圖時在需要添加交互事件的路徑中添加如下代碼
1 try { 2 //id為空會報錯 3 ctx.addHitRegion({ "id": "excited" }); 4 } catch (e) { 5 alert("請在chrome://flags中啟用【實驗性畫布功能】或在firefox中輸入about:config使canvas.hitregions.enabled值為true以開啟更多功能~~~///(^v^)\\\~~~"); 6 }
需要注意的是id的值不能為空
然后,這樣引用
1 document.getElementById(selector).addEventListener('click', function (event) { 2 if (event.region === 'excited') { 3 ... 4 } 5 }, false);
相當於把需要的路徑標識出來后面使用,非常方便。
注意:該接口目前尚在實驗中,在未來版本的瀏覽器中其語法和行為可能有所改變。未納入標准之前,可以玩玩