flex 图片旋转(解决公转和自转问题)
?
在Flex中圖片的旋轉(zhuǎn)是既有公轉(zhuǎn)和自轉(zhuǎn)的。這樣在圖片旋轉(zhuǎn)的時(shí)候就有一定小麻煩;
為了更好地說(shuō)明問(wèn)題,先引入兩個(gè)概念:“自轉(zhuǎn)”和“公轉(zhuǎn)”。想象一下,地球在繞著太陽(yáng)公轉(zhuǎn)的同時(shí),它自己也在自轉(zhuǎn)。Flash應(yīng)用中的顯示對(duì)象可以進(jìn)行自身的自轉(zhuǎn),也可以繞著某個(gè)點(diǎn)公轉(zhuǎn),也可以兩者同時(shí)進(jìn)行。
?
實(shí)現(xiàn)旋轉(zhuǎn)常用的方法
1)??????displayObject.rotation=degree; //實(shí)現(xiàn)顯示對(duì)象的自轉(zhuǎn)(flash|Flex)
2)??????spark.effects.Rotate; //實(shí)現(xiàn)顯示對(duì)象的自轉(zhuǎn)(Flex)
3)??????matrix.rotate; //同時(shí)實(shí)現(xiàn)顯示對(duì)象的自轉(zhuǎn)和公轉(zhuǎn)(flash|Flex)
本文重點(diǎn)介紹matrix.rotate的實(shí)現(xiàn)細(xì)節(jié)。
最近做的一個(gè)小項(xiàng)目需要實(shí)現(xiàn)“圖片繞中心旋轉(zhuǎn)”的效果。在網(wǎng)上搜索了相關(guān)的資料,在很多帖子中都推薦使用Matrix來(lái)實(shí)現(xiàn)。代碼如下:?
var matrix:Matrix = img.transform.matrix;
matrix.translate(-img.width/2,-img.height/2);
matrix.rotate(radian);
matrix.translate(+img.width/2,+img.height/2);
img.transform.matrix = matrix;
相信做過(guò)“圖片繞中心旋轉(zhuǎn)”效果的朋友都見(jiàn)過(guò)這段代碼。實(shí)現(xiàn)原理就是先把圖片的中點(diǎn)移動(dòng)到左上角,然后進(jìn)行旋轉(zhuǎn)操作,最后再把圖片移回來(lái)。看起來(lái)很好理解,但是這段代碼在我的Flex應(yīng)用中卻不能正常工作。又回到網(wǎng)上搜索了很長(zhǎng)時(shí)間,發(fā)現(xiàn)這段代碼出現(xiàn)在很多論壇博客中,沒(méi)有一個(gè)說(shuō)這段代碼有問(wèn)題的。通過(guò)測(cè)試,最后才發(fā)現(xiàn)了問(wèn)題所在:此段代碼需要在特定的前提下才能正常使用。這個(gè)前提下面會(huì)細(xì)說(shuō)。現(xiàn)在我們先來(lái)看matix.rotate這個(gè)方法究竟做了什么。
?
matix.rotate做了什么
在Flash IDE中做了一系列試驗(yàn):在場(chǎng)景中放置一個(gè)影片剪輯,影片剪輯的注冊(cè)點(diǎn)分別在左上角和中心,影片剪輯的x,y分別在(0,0)和(70,70)。
試驗(yàn)的結(jié)論是:
matrix.rotate方法讓目標(biāo)對(duì)象同時(shí)進(jìn)行“自轉(zhuǎn)和公轉(zhuǎn)”,旋轉(zhuǎn)的實(shí)現(xiàn)跟“影片剪輯的注冊(cè)點(diǎn)的位置”和“影片剪輯的初始位置”有很大的關(guān)系。詳見(jiàn)下面的4個(gè)場(chǎng)景(灰色框?yàn)閳?chǎng)景,黑色框?yàn)樾D(zhuǎn)目標(biāo)):
場(chǎng)景1:影片剪輯的注冊(cè)點(diǎn)在左上角,影片剪輯在場(chǎng)景中的初始位置為(0,0)。
結(jié)果:影片剪輯自轉(zhuǎn)的同時(shí)繞著(0,0)公轉(zhuǎn)。因?yàn)楣D(zhuǎn)的半徑為0,所以沒(méi)有體現(xiàn)在圖片上。
?
場(chǎng)景2:影片剪輯的注冊(cè)點(diǎn)在左上角,影片剪輯在場(chǎng)景中的初始位置為(70,70)。
結(jié)果:影片剪輯自轉(zhuǎn)的同時(shí)繞著(0,0)公轉(zhuǎn),公轉(zhuǎn)的半徑為70。
?
場(chǎng)景3:影片剪輯的注冊(cè)點(diǎn)在中心,影片剪輯在場(chǎng)景中的初始位置為(0,0)。
結(jié)果:影片剪輯自轉(zhuǎn)的同時(shí)繞著(0,0)公轉(zhuǎn),因?yàn)楣D(zhuǎn)的半徑為0,所以沒(méi)體現(xiàn)在圖上。
?
場(chǎng)景4:影片剪輯的注冊(cè)點(diǎn)在中心,影片剪輯在場(chǎng)景中的初始位置為(125,30)。
結(jié)果:影片剪輯自轉(zhuǎn)的同時(shí)繞著(0,0)公轉(zhuǎn),因?yàn)楣D(zhuǎn)的半徑為125。
?
在上面的這些場(chǎng)景中,第三個(gè)場(chǎng)景的影片剪輯是繞中心旋轉(zhuǎn)的。也就是說(shuō),影片剪輯在滿足以下兩個(gè)條件時(shí),才能使用matrix.rotate方法實(shí)現(xiàn)繞中心旋轉(zhuǎn)。?
1)??影片剪輯的注冊(cè)點(diǎn)在中心;
2)??影片剪輯的中心點(diǎn)與場(chǎng)景(或父影片剪輯)的(0,0)重疊。
再重新觀察上面的那段代碼:
var matrix:Matrix = img.transform.matrix;
matrix.translate(-img.width/2,-img.height/2);
matrix.rotate(radian);
matrix.translate(+img.width/2,+img.height/2);
img.transform.matrix = matrix;
代碼中使用了translate方法,很顯然目的就是為了讓img的中心點(diǎn)與父影片剪輯的(0,0)點(diǎn)重疊。所以,使用這段代碼的前提條件是:
1)??在Flash IDE中開(kāi)發(fā);(才能調(diào)整注冊(cè)點(diǎn)的位置)
2)??目標(biāo)影片剪輯的注冊(cè)點(diǎn)在中心;
3)??把目標(biāo)影片剪輯放在一個(gè)空影片剪輯中,并設(shè)置x,y為(0,0)。
善了個(gè)哉的,網(wǎng)上這么多篇文章提到這段代碼,居然沒(méi)有一篇提到上述的條件,坑爹吶!
?如果是在Flash IDE環(huán)境中進(jìn)行開(kāi)發(fā),實(shí)現(xiàn)旋轉(zhuǎn)還有一個(gè)更方便的可選項(xiàng),那就是MatrixTransformer.rotateAroundInternalPoint和MatrixTransformer.rotateAroundExternalPoint。這兩個(gè)靜態(tài)方法用起來(lái)可比matrix.rotate方便多了。不需要考慮注冊(cè)點(diǎn)的問(wèn)題,也不需要把目標(biāo)影片剪輯放到空的影片剪輯中。只可惜在Flex中沒(méi)有這個(gè)類。
?
如何在Flex中實(shí)現(xiàn)旋轉(zhuǎn)
在Flex環(huán)境中沒(méi)有影片剪輯,它使用自己的一套組件,注冊(cè)點(diǎn)默認(rèn)在左上角,不能調(diào)整注冊(cè)點(diǎn)的位置。我們?nèi)绾螌?shí)現(xiàn)組件的旋轉(zhuǎn)呢?
1)??使用rotation屬性。但是因不能調(diào)整組件的注冊(cè)點(diǎn),所以只能讓組件繞左上角旋轉(zhuǎn)。
2)??使用spark.effects.Rotate類。可以通過(guò)設(shè)置autoCenterTransform為true或false來(lái)控制組件是繞中心點(diǎn)旋轉(zhuǎn)還是繞左上角旋轉(zhuǎn)。
3)??使用matrix.rotate方法。通過(guò)控制組件的“自轉(zhuǎn)”和“公轉(zhuǎn)”來(lái)實(shí)現(xiàn)我們需要的旋轉(zhuǎn)。
調(diào)用matrix.rotate方法,會(huì)使目標(biāo)對(duì)象同時(shí)進(jìn)行“自轉(zhuǎn)”和“公轉(zhuǎn)”,這可以從上面的場(chǎng)景2和場(chǎng)景4中明顯看出。其實(shí)在場(chǎng)景1中和場(chǎng)景3中,目標(biāo)對(duì)象也是同時(shí)進(jìn)行了“自轉(zhuǎn)”和“公轉(zhuǎn)”,只是因?yàn)楣D(zhuǎn)的半徑為0,所以看不出來(lái)而已。
如果目標(biāo)對(duì)象的初始位置不是(0,0)的話,如何實(shí)現(xiàn)目標(biāo)對(duì)象的繞點(diǎn)旋轉(zhuǎn)呢?首先,對(duì)于旋轉(zhuǎn)目標(biāo)的自轉(zhuǎn),我們不需要做什么。因?yàn)樽赞D(zhuǎn)是必須的。而對(duì)于旋轉(zhuǎn)目標(biāo)的公轉(zhuǎn),我就需要做一些額外的操作了。因?yàn)楣D(zhuǎn)改變了旋轉(zhuǎn)目標(biāo)的位置,這也是影響旋轉(zhuǎn)目標(biāo)是否繞點(diǎn)旋轉(zhuǎn)的因素。調(diào)用matrix.rotate方法時(shí),我們不能阻止旋轉(zhuǎn)目標(biāo)的公轉(zhuǎn),所以,解決辦法只能是:在調(diào)用matrix.rotate之前,取得旋轉(zhuǎn)中心點(diǎn)的位置,然后在旋轉(zhuǎn)后,再取得旋轉(zhuǎn)中心點(diǎn)的位置,然后計(jì)算點(diǎn)的位移,最后用matrix.translate方法將旋轉(zhuǎn)目標(biāo)調(diào)整到“正確位置”。
下面兩組圖是兩個(gè)不同旋轉(zhuǎn)中心下的旋轉(zhuǎn),旋轉(zhuǎn)之后,我們?cè)偻ㄟ^(guò)matrix.translate方法把旋轉(zhuǎn)后的粉色的原點(diǎn)移動(dòng)到它原始的狀態(tài)及可。見(jiàn)圖。
注冊(cè)點(diǎn)在左上角,繞中心旋轉(zhuǎn)。
?
?
注冊(cè)點(diǎn)在左上角,繞左上角旋轉(zhuǎn)。這種情況下,使用matrix.rotate方法顯然是多余的,因?yàn)楹?jiǎn)單地使用displayObject.rotation屬性就可以實(shí)現(xiàn)想要的旋轉(zhuǎn)了。在這里我們使用matrix.rotate方法是為了更好地說(shuō)明matrix.rotate方法的實(shí)現(xiàn)細(xì)節(jié)。
?
注冊(cè)點(diǎn)在中心,繞中心點(diǎn)旋轉(zhuǎn)。如果需要在Flash中用matrix.rotate方法實(shí)現(xiàn)旋轉(zhuǎn),且不依賴父影片剪輯,則使用該方法。
?
注冊(cè)點(diǎn)在中心,繞左上角旋轉(zhuǎn)。
?
最后提供一段代碼,此代碼實(shí)現(xiàn)讓一個(gè)注冊(cè)點(diǎn)在左上角的對(duì)象繞它的中心點(diǎn)旋轉(zhuǎn)。代碼如下:
//旋轉(zhuǎn)之前獲取旋轉(zhuǎn)對(duì)象的中心點(diǎn)
var p1:Point = rotatedObject.localToGlobal(new Point(rotatedObject.width/2, rotatedObject.height/2));
//旋轉(zhuǎn)
var matrix1:Matrix = rotatedObject.transform.matrix;
matrix1.rotate(radian);
rotatedObject.transform.matrix = matrix1;
//旋轉(zhuǎn)后獲取旋轉(zhuǎn)對(duì)象的中心點(diǎn)
var p2:Point = rotatedObject.localToGlobal(new Point(rotatedObject.width/2, rotatedObject.height/2));
//位移
var matrix2:Matrix = rotatedObject.transform.matrix;
matrix2.translate(p1.x-p2.x,p1.y-p2.y);
rotatedObject.transform.matrix = matrix2;
?
?
2012-5-5補(bǔ)充:
更新一個(gè)新的旋轉(zhuǎn)方式。這個(gè)方法是MatrixTransformer類中rotateAroundInternalPoint靜態(tài)方法的做法。
假設(shè)有一個(gè)圖片A,我們希望將圖片繞O點(diǎn)旋轉(zhuǎn)。O點(diǎn)在圖片內(nèi)部的坐標(biāo)是(x,y)。我們可以先移動(dòng)圖片,讓圖片的O點(diǎn)與父容器的(0,0)點(diǎn)重合,調(diào)用rotate方法進(jìn)行旋轉(zhuǎn),然后再將圖片移動(dòng)回正確的位置。代碼如下:
?
var point:Point = new Point(x, y);
point = m.transformPoint(point);//將圖片內(nèi)部的點(diǎn)轉(zhuǎn)換成父容器坐標(biāo)的點(diǎn)
m.tx -= point.x;
m.ty -= point.y;
m.rotate(angleDegrees*(Math.PI/180));
m.tx += point.x;
m.ty += point.y;
?
MatrixTransformer類的另一個(gè)rotateAroundExternalPoint靜態(tài)方法的做法類似,但是因?yàn)槭且浴巴獠康狞c(diǎn)”為旋轉(zhuǎn)中心,所以代碼有些不同:
?
var point:Point = new Point(x, y);
m.tx -= point.x;
m.ty -= point.y;
m.rotate(angleDegrees*(Math.PI/180));
m.tx += point.x;
m.ty += point.y;
?
在這個(gè)方法中,“外部的點(diǎn)”是在父容器的坐標(biāo)空間中,所以不需要再轉(zhuǎn)換該點(diǎn)了。
?
另一個(gè)旋轉(zhuǎn)方式:
這個(gè)方法是某Transform tool中的做法。注意,這個(gè)方法跟上邊補(bǔ)充的第一種方法不一樣。
anchor = new Point(width/2, height/2); //旋轉(zhuǎn)對(duì)象的坐標(biāo)空間內(nèi)旋轉(zhuǎn)對(duì)象的中心點(diǎn)
//?把旋轉(zhuǎn)對(duì)象的中心點(diǎn)轉(zhuǎn)換成父容器坐標(biāo)空間中的點(diǎn)
var globalAnchor:Point = matrix.transformPoint(anchor);??
// calculates position
var m:Matrix = new Matrix(); //創(chuàng)建了一個(gè)新的matrix對(duì)象
//下面的操作是把這個(gè)matrix對(duì)象轉(zhuǎn)化成我們想要的
m.translate(-anchor.x, -anchor.y);//將目標(biāo)的中心點(diǎn)移動(dòng)到與父容器坐標(biāo)系統(tǒng)的(0,0)重疊
m.rotate((rotation + angle)*Math.PI/180);//旋轉(zhuǎn)目標(biāo)
m.translate(globalAnchor.x, globalAnchor.y);//將目標(biāo)的中心點(diǎn)移動(dòng)到合適的位置
為什么var globalAnchor:Point = matrix.transformPoint(anchor);能把旋轉(zhuǎn)對(duì)象的中心點(diǎn)的坐標(biāo)轉(zhuǎn)換成旋轉(zhuǎn)對(duì)象的父容器的坐標(biāo)呢?
?當(dāng)旋轉(zhuǎn)對(duì)象放在父容器中,沒(méi)有應(yīng)用任何matrix變形時(shí),它的坐標(biāo)系統(tǒng)和父容器的坐標(biāo)系統(tǒng)是重疊的,也就是說(shuō),旋轉(zhuǎn)對(duì)象的中心點(diǎn)在父容器坐標(biāo)系統(tǒng)中的坐標(biāo)就是它的本地坐標(biāo)。當(dāng)旋轉(zhuǎn)對(duì)象發(fā)生matrix變形后,旋轉(zhuǎn)對(duì)象的中心點(diǎn)在父容器坐標(biāo)系統(tǒng)的坐標(biāo)發(fā)生了變化,而這個(gè)變化正是應(yīng)用在旋轉(zhuǎn)對(duì)象上的matrix對(duì)象帶來(lái)變形效果。因此,matrix的transformPoint方法能把本地坐標(biāo)轉(zhuǎn)換成父容器坐標(biāo)。
左上角的圖形是變形前的,右邊的圖形是變形之后的。中心點(diǎn)1的本地坐標(biāo)是(2,2),因?yàn)樵跊](méi)有使用任何matrix效果時(shí),它的本地坐標(biāo)系統(tǒng)跟父容器的坐標(biāo)系統(tǒng)是重疊的。因此它在父容器中的坐標(biāo)也是(2,2)。這個(gè)點(diǎn)在經(jīng)過(guò)matrix變形后,就變成了(9,5),也就是圖形中心點(diǎn)在父容器坐標(biāo)系統(tǒng)中的新坐標(biāo)。
解決方案就是把圖片放到父容器的(0,0)點(diǎn)進(jìn)行旋轉(zhuǎn),在平一會(huì)你想好要的位置;
?
public function draw( displayTarget : Sprite , point : Point , index : int ) : void { var graphics : Graphics = displayTarget.graphics ; var metrix : Matrix = new Matrix( 1.0 , 0.0 , 0.0 , 1.0 , 0 , 0 ); graphics.beginBitmapFill( this._image , metrix , false , true ); graphics.drawRect( 0,0, this.size, this.size); graphics.endFill();//求等腰三角形斜邊長(zhǎng) 的一辦 var halfDiagonal : Number = (this.size/2)*Math.sqrt(2); var rotateAngle : Number = 0;displayTarget.rotation = angle;if(0 <= angle && angle < 45) { rotateAngle = (angle+45)* (Math.PI/180); displayTarget.x = point.x - Math.cos(rotateAngle)*halfDiagonal; displayTarget.y = point.y - Math.sin(rotateAngle)*halfDiagonal;}else if(45 <= angle && angle < 135) { rotateAngle = (angle - 45)* (Math.PI/180);displayTarget.x = point.x + (Math.sin(rotateAngle)*halfDiagonal); displayTarget.y = point.y - (Math.cos(rotateAngle)*halfDiagonal); } else if(135 <= angle && angle < 225) { rotateAngle = (angle - 135)* (Math.PI/180);displayTarget.x = point.x + (Math.cos(rotateAngle)*halfDiagonal); displayTarget.y = point.y + (Math.sin(rotateAngle)*halfDiagonal); } else if(225 <= angle && angle < 315) { rotateAngle = (angle - 225)* (Math.PI/180);displayTarget.x = point.x - (Math.sin(rotateAngle)*halfDiagonal); displayTarget.y = point.y + (Math.cos(rotateAngle)*halfDiagonal); } else if(315 <= angle && angle < 360) { rotateAngle = (angle - 315)* (Math.PI/180);displayTarget.x = point.x - (Math.cos(rotateAngle)*halfDiagonal); displayTarget.y = point.y - (Math.sin(rotateAngle)*halfDiagonal); }}
轉(zhuǎn)載于:https://www.cnblogs.com/youngKen/p/3430821.html
總結(jié)
以上是生活随笔為你收集整理的flex 图片旋转(解决公转和自转问题)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 【最新】docker 安装elastic
- 下一篇: [bzoj2743]采花