5坑之hammer手勢操作之同時縮放、旋轉、移動畫布canvas

在使用hammer.js開發移動終端的繪圖類App時,我們需要用手指來處理畫布的縮放/旋轉和移動。

一般來說我們會考慮到使用 DOM 的CSS3 屬性transform來操作。比如:

scale(x,y)

translate(x,y)

rotate(d)

但是編碼時,會有不少坑。如:

坑1:分別處理scale/rotate等時,影響其他屬性。

分別處理touch的rotatemove,pinchmove事件時,如果我們只是操作:

$(“#id”).css(“transform”,”rotate(“ + e.rotation + “deg)”);

會發現角度雖然改變了,但是縮放又變回了原值。


同樣,在pinchmove中處理scale時也是如此。


開始時,想使用matrix來處理這個問題,後來涉及到較複雜的計算就放棄了(總之沒達到我要的效果,也不知是計算的問題還是調用次序的問題)。

後來發現,其實可以同時操作,寫法是在每個函數中增加空格。如:

$(“#id”).css(“transform”,”translate(“ + e.deltaX + “px,” + e.deltaY + “px) scale(“ + e.scale + “,” + e.scale + “) rotate(“ + e.rotation + “deg)”);


坑2:需要注意的是,不要忘了在相應的數值後加上deg和px,否則會執行錯誤。


坑3:手指捏放時需要將e.scale的作用減弱,否則會出現縮放很快的情況。

我使用的方法是連續開3次平方根:

var scale = Math.sqrt(Math.sqrt(Math.sqrt(e.scale)));

這樣處理後感覺縮放速度感受更好了。


坑4:scale值是相對於canvas初始值的,這個不算很坑,但需要了解。


坑5:每次旋轉時,需要考慮旋轉開始時的角度,要根據當前的canvas角度做相應處理,否則會產生跳動。

代碼如下,自己體會吧:

var initAngle = 0;

var preAngle = 0;

var tempAngleFlag = 0;

var deltaAngle = 0;

var startRotateAngle = 0;


在手勢處理的switch中,略去無關代碼

case "rotatestart":

//當每次rotatestart時,e.rotation不從0開始。

startRotateAngle = e.rotation.toFixed(2);

tempAngleFlag = 0;

break;

case

"rotatemove":

//轉動的角度

if (cvsObj.obj != null) {

if(tempAngleFlag == 0){

preAngle = startRotateAngle;

tempAngleFlag ++;

}else{

deltaAngle = e.rotation - preAngle;

cvsObj.current.rotate = initAngle + deltaAngle; //cvsObj.current.rotate 用來記錄當前canvas對象的角度

cvsObj.current.rotate = cvsObj.current.rotate % 360; //防止超出360

}

scale = "scale(" + cvsObj.scale + "," + cvsObj.scale + ")";

rotate = "rotate(" + cvsObj.current.rotate + "deg)";

translate = "translate(" + e.deltaX + "px," + e.deltaY + "px)";

style = translate + " " + scale + " " + rotate;

$("#id").css("transform",style);

}

break;

case

"rotateend":

initAngle = cvsObj.current.rotate;

break;


5坑之hammer手勢操作之同時縮放、旋轉、移動畫布canvas


分享到:


相關文章: