上一篇Canvas的博文寫完后,有位朋友希望能對Canvas繪制出來的圖像進行點擊、拖拽等操作,因為Canvas繪制出的圖像能很好的美化。好像是想做爐石什么的游戲,我也沒玩過。
Canvas在我的理解中就好像在一張畫布上繪制圖像,它只能看到卻“摸”不到,那要如何進行操作呢。我不知道網上是怎么做的,這里用自己的想法做了個DEMO分享給大家。
思路:
雖然Canvas不能拖拽,但div可以拖拽,那怎么把二者結合起來呢。初步想法是將一個與Canvas圖像大小差不多的div覆蓋在其上,在拖拽div時將獲取的光標坐標修正后傳給Canvas繪制函數并刷新圖像的位置。
既然要覆蓋,先做些準備工作:
1.將div與Canvas畫布均position:absolute,否則無法重疊。
2.將div的z-index值設置大點,保證其在Canvas畫面之上。
準備工作完成后,我們先來看div的拖拽:
var divObj=document.getElementById("cover");var moveFlag=false;
divObj.οnmοusedοwn=function(e){
moveFlag=true;var clickEvent=window.event||e;var mwidth=clickEvent.clientX-divObj.offsetLeft;var mheight=clickEvent.clientY-divObj.offsetTop;
document.οnmοusemοve=function(e){var moveEvent=window.event||e;if(moveFlag){
divObj.style.left=moveEvent.clientX-mwidth+"px";
divObj.style.top=moveEvent.clientY-mheight+"px";
divObj.οnmοuseup=function(){
moveFlag=false;
}
}
}
};
來解讀下這段代碼:首先獲取div對象,設置拖拽標志moveFlage,當onmousedown時為true表示可以拖動,當onmouseup時為false表示不能拖動了。
var clickEvent=window.event||e;var mwidth=clickEvent.clientX-divObj.offsetLeft;var mheight=clickEvent.clientY-divObj.offsetTop;
這三行代碼是為了修正光標位置。當點擊時,記錄下光標在div上的位置。mwidth和mheight表示光標落點相對于div左邊和上邊的距離。如果不加修正:
這就是不加修正的結果,當光標點下時,div的坐標即左上角會與光標坐標一致。
修正后:
點擊時光標總會“粘”在div某點上。
接下來繪制圖片:
首先定義全局變量X和Y,它們是為了實時更新圖像的繪制坐標。
var ctx=document.getElementById("myCanvas").getContext("2d");var img=document.getElementById("myImg");functiondrawImg(){
ctx.clearRect(0,0,1000,500);
ctx.beginPath();
ctx.drawImage(img,X,Y);
ctx.closePath();
ctx.stroke();
}
window.οnlοad=function(){
setInterval(drawImg,1);
}
獲取“畫筆”,獲取圖片對象。這里setInterval循環執行繪制圖片的函數,以刷新圖片的位置,setInterval的間隔值越小,拖拽起來越“流暢”。
同時別忘了clearRect,當圖片移動到下一個位置時,清除上一個位置的圖片,參數為Canvas畫布的坐標和尺寸。
在拖拽時將修正后的光標坐標傳給X、Y:
X=moveEvent.clientX-mwidth;
Y=moveEvent.clientY-mheight;
最后加上div和圖像的活動范圍:
if(moveEvent.clientX<=mwidth){
divObj.style.left=0+"px";
X=0;
}if(parseInt(divObj.style.left)+divObj.offsetWidth >=1000){
divObj.style.left=1000 - divObj.offsetWidth+"px";
X=1000 -divObj.offsetWidth;
}if(moveEvent.clientY<=mheight){
divObj.style.top=0+"px";
Y=0;
}if(parseInt(divObj.style.top)+divObj.offsetHeight>=500){
divObj.style.top=500-divObj.offsetHeight+"px";
Y=500-divObj.offsetHeight;
}
這個就看個人的要求了,注意是要同時限定div和圖片的活動范圍。1000與500為本例的畫布大小,如果是在整個頁面里活動就換成innerWidth或innerHeight。
徹底隱藏div看看效果:
最后說下點擊事件,這里要注意的是在拖拽的過程中onmousedown與onmouseup二者就構成了一個click過程,但我們不希望在拖拽結束后觸發點擊事件。
這里有個比較簡單的辦法,定義一個clickFlag默認為false,當onmousedown時設為true,若進行了onmousemove事件時設為false。
在最后onmouseup時判斷clickFlag的值,為true時才觸發點擊事件。也就是說當你按下鼠標時,只有不發現移動,松開鼠標時才會觸發點擊事件。
整理后的JS代碼:
//繪制圖片坐標
var X=0;var Y=0;//js部分
var divObj=document.getElementById("cover");var moveFlag=false;//區別moueseup與click的標志
var clickFlag=false;//拖拽函數
divObj.οnmοusedοwn=function(e){
moveFlag=true;
clickFlag=true;var clickEvent=window.event||e;var mwidth=clickEvent.clientX-divObj.offsetLeft;var mheight=clickEvent.clientY-divObj.offsetTop;
document.οnmοusemοve=function(e){
clickFlag=false;var moveEvent=window.event||e;if(moveFlag){
divObj.style.left=moveEvent.clientX-mwidth+"px";
divObj.style.top=moveEvent.clientY-mheight+"px"; 將鼠標坐標傳給Canvas中的圖像
X=moveEvent.clientX-mwidth;
Y=moveEvent.clientY-mheight; 下面四個條件為限制div以及圖像的活動邊界
if(moveEvent.clientX<=mwidth){
divObj.style.left=0+"px";
X=0;
}if(parseInt(divObj.style.left)+divObj.offsetWidth >=1000){
divObj.style.left=1000 - divObj.offsetWidth+"px";
X=1000 -divObj.offsetWidth;
}if(moveEvent.clientY<=mheight){
divObj.style.top=0+"px";
Y=0;
}if(parseInt(divObj.style.top)+divObj.offsetHeight>=500){
divObj.style.top=500-divObj.offsetHeight+"px";
Y=500-divObj.offsetHeight;
}
divObj.οnmοuseup=function(){
moveFlag=false;if(clickFlag){
alert("點擊生效");
}
}
}
}
};
本例到此結束,更多功能大家有興趣可以自己開發,感謝您的瀏覽,也感謝每個對我這菜鳥提意見的人。