項目的一個新需求,動態生成矩形框,鼠標點擊拖動改變矩形框的位置,並能夠調整大小。html
以前作過一個小demo,需求相似,可是在canvas內只有一個矩形框,拖動移動,當時記得是用isPointInPath()直接判斷鼠標是否點在了矩形框之內。新需求的矩形框個數爲n,通過測試,isPointinPath實現過程當中有bug,並不能精準定位到具體點擊到canvas的某一個矩形框。通過一系列的頭腦風暴,纔想出了解決辦法,才發現原來是最簡單的方法,可是在思考的當初就被pass了,見代碼:canvas
<body> <canvas id="canvas" width="400" height="300"> </canvas> </body>
小demo,不作其餘修飾,直接寫邏輯吧。數組
第一步,建立一個容器,以保存Canvas內繪製的元素點。Canvas是一種非保留性的繪圖界面,即不會記錄過去執行的繪圖操做,而是保持最終結果(構成圖像的彩色像素)。dom
1 // canvas 矩形框集合 2 var rects=[]; 3 function rectar(x,y,width,height){ 4 this.x = x; 5 this.y = y; 6 this.width = width; 7 this.height = height; 8 this.isSelected = false; 9 };
1 function drawRect() { 2 // 清除畫布,準備繪製 3 context.clearRect(0, 0, canvas.width, canvas.height); 4 5 // 遍歷全部矩形框 6 for(var i=0; i<rects.length; i++) { 7 var rect = rects[i]; 8 9 // 繪製矩形 10 context.strokeStyle="#FF0000"; 11 context.strokeRect(rect.x,rect.y,rect.width,rect.height,rect.color); 12 13 if (rect.isSelected) { 14 context.lineWidth = 50; 15 } 16 else { 17 context.lineWidth = 10; 18 } 19 } 20 }
這是一個繪製函數,由於在Canvas的全部操做,所有都是從新繪製的(先清除,在繪製),每次程序刷新畫布時,會先使用 clearRect() 方法清除畫布上的全部內容。但不用小心這樣會形成畫布閃爍,即畫布上的圓圈一會兒所有消失,而後一會兒又從新出現。由於Canvas針對這個問題進行了優化,會在全部繪圖邏輯執行完畢後才清除或繪製全部內容,保證最終結果的流暢。而後遍歷矩形數組 其中的x,y,width,height來畫矩形。函數
*這裏個人項目是根據病變位置動態生成的矩形框,每一次生成矩形框,都要把它的位置信息添加到數組中,這裏就直接建立矩形框了,能夠根據本身需求改造測試
1 function addRandomRect() { 2 var x=10; 3 var y=10; 4 var width=100; 5 var height=100; 6 // 建立一個新的矩形對象 7 var rect=new rectar(x,y,width,height); 8 9 // 把它保存在數組中 10 rects.push(rect); 11 // 從新繪製畫布 12 drawRect(); 13 };
1 var SelectedRect; 2 var x1; 3 var y1; 4 var right=false; 5 var widthstart,widthend; 6 var heightstart,heightend; 7 8 function canvasClick(e) { 9 // 取得畫布上被單擊的點 10 var clickX = e.pageX - canvas.offsetLeft; 11 var clickY = e.pageY - canvas.offsetTop; 12 13 // 查找被單擊的矩形框 14 for(var i=rects.length-1; i>=0; i--) { 15 var rect = rects[i]; 16 17 widthstart=rect.x; 18 widthend=rect.x+rect.width; 19 20 heightstart=rect.y; 21 heightend=rect.y+rect.height; 22 23 // 判斷這個點是否在矩形框中 24 if ((clickX>=widthstart&&clickX<(widthend-20))&&(clickY>=heightstart)&&(clickY<(heightend-20))) { 25 console.log(clickX); 26 // 清除以前選擇的矩形框 27 if (SelectedRect != null) SelectedRect.isSelected = false; 28 SelectedRect = rect; 29 x1=clickX-SelectedRect.x; 30 y1=clickY-SelectedRect.y; 31 //選擇新圓圈 32 rect.isSelected = true; 33 34 // 使圓圈容許拖拽 35 isDragging = true; 36 37 //更新顯示 38 drawRect(); 39 //中止搜索 40 return; 41 }; 42 /* 43 設置拉伸的界限。 44 */ 45 // if ((clickX>=(widthend-20))&&(clickY>=(heightend-20))) 46 // { 47 // SelectedRect = rect; 48 // right=true; 49 // }
//18-02-01改
if ((clickX>=(widthend-20)&&((clickX<=(widthend+20)))&&(clickY>=(heightend-20))&&(clickY>=(heightend+20)))
{
SelectedRect = rect;
right=true;
}
50 }
51 }
代碼中23行爲判斷具體點擊哪一個元素的語句,其實很簡單,當初繞了好久,很簡單直接判斷鼠標點擊點是否在矩形框以內便可,不管是哪一個矩形框,只要在矩形框以內,就把當前矩形框設置爲點擊的矩形框。29行判斷鼠標點擊點相對於矩形框的位置。42-49行,是鼠標拉伸改變大小的判斷,能夠設置矩形四個角拉伸,但我認爲太複雜了,只保留了右下角拉伸的點擊判斷,操做更簡單一些。優化
function dragRect(e) { // 判斷矩形是否開始拖拽 if (isDragging == true) { // 判斷拖拽對象是否存在 if (SelectedRect != null) { // 取得鼠標位置 var x = e.pageX - canvas.offsetLeft; var y = e.pageY - canvas.offsetTop; // 將圓圈移動到鼠標位置 SelectedRect.x= x-x1; SelectedRect.y= y-y1; // 更新畫布 drawRect(); } }
//判斷是否開始拉伸 if (right) {
//設置拉伸最小的邊界 if ((e.pageX - canvas.offsetLeft-SelectedRect.x)>50) { SelectedRect.width=e.pageX - canvas.offsetLeft-SelectedRect.x; } else { SelectedRect.width=50; } console.log(SelectedRect.width); if((e.pageY - canvas.offsetTop-SelectedRect.y)>50){ SelectedRect.height=e.pageY - canvas.offsetTop-SelectedRect.y; } else { SelectedRect.height=50; } drawRect(); } };
以上就完成了對矩形框的基本操做,而後添加onmouseup的函數和調用函數:動畫
var isDragging = false; function stopDragging() { isDragging = false; right=false; };
function clearCanvas() {
// 去除全部矩形
rects = [];this
// 從新繪製畫布.spa
drawCircles();
}
window.onload = function() { canvas = document.getElementById("canvas"); context = canvas.getContext("2d"); canvas.onmousedown = canvasClick; canvas.onmouseup = stopDragging; canvas.onmouseout = stopDragging; canvas.onmousemove =dragRect;
; };