標籤:
前面關於旋轉的兩篇我們利用CABasicAnimation來實現旋轉動畫,其實在SceneKit中,有一種更為簡單的方法去實現一些基礎動畫,那就是SCNAction,它的執行對象是SCNNode。
一個簡單的例子:
SCNAction *shipMoveAction = [SCNAction moveTo:SCNVector3Make(10,10,5) duration:4];[shipRotationNode runAction:shipMoveAction];
上面代碼很容易理解shipRotationNode 動畫移動到(10,10,5)這個位置,時間間隔為4s。
我們下面簡單介紹一下 SCNAction 主要的API:
+ (SCNAction *)moveByX:(CGFloat)deltaX y:(CGFloat)deltaY z:(CGFloat)deltaZ duration:(NSTimeInterval)duration //將node從x,y,z上各移動多少距離+ (SCNAction *)moveBy:(SCNVector3)delta duration:(NSTimeInterval)duration //同上,只不過傳入參數為SCNVector3+ (SCNAction *)moveTo:(SCNVector3)location duration:(NSTimeInterval)duration//將node移動到location這個位置+ (SCNAction *)rotateByX:(CGFloat)xAngle y:(CGFloat)yAngle z:(CGFloat)zAngle duration:(NSTimeInterval)duration//將node從x,y,z上各旋轉多少度+ (SCNAction *)rotateToX:(CGFloat)xAngle y:(CGFloat)yAngle z:(CGFloat)zAngle duration:(NSTimeInterval)duration//將node從x,y,z上旋轉到指定角度+ (SCNAction *)rotateToX:(CGFloat)xAngle y:(CGFloat)yAngle z:(CGFloat)zAngle duration:(NSTimeInterval)duration shortestUnitArc:(BOOL)shortestUnitArc// 同上,與上面的方法區別在於多了shortestUnitArc 這個參數,BOOL值。//舉個例子:我們需要將一個node從 0度旋轉到270度,//如果將shortestUnitArc設定為NO,node會順時針旋轉到270度;//如果將shortestUnitArc設定為YES,node會逆時針旋轉90度到270度,//即選擇最小的旋轉角度旋轉到特定的度數。預設為NO。+ (SCNAction *)rotateByAngle:(CGFloat)angle aroundAxis:(SCNVector3)axis duration:(NSTimeInterval)duration// 沿著特定的軸旋轉angle度。前面旋轉都是沿x,y,z軸旋轉,都是互相垂直的,//大家有沒有想過如何沿著與x軸成45度夾角的方向旋轉node? //這個API大家這裡留意一下,//上篇提到的不在X-Z 這個平面旋轉,會用這個方法在後面的demo中解決。+ (SCNAction *)rotateToAxisAngle:(SCNVector4)axisAngle duration:(NSTimeInterval)duration// SCNVector4(x,y,z,angle) 沿著特定的軸旋轉到angle度。//這裡解釋一下angle 類似π,如果angle=2,//我們可不能理解為旋轉到2度,而是旋轉到2/π*180 度。+ (SCNAction *)scaleBy:(CGFloat)scale duration:(NSTimeInterval)sec//縮小(放大)多少+ (SCNAction *)scaleTo:(CGFloat)scale duration:(NSTimeInterval)sec//縮小(放大)到多少+ (SCNAction *)fadeInWithDuration:(NSTimeInterval)sec//字面意思可以理解,淡入。將node 的opacity 漸漸層成1+ (SCNAction *)fadeOutWithDuration:(NSTimeInterval)sec// 淡出+ (SCNAction *)fadeOpacityBy:(CGFloat)factor duration:(NSTimeInterval)sec//將node 的opacity 漸漸層化特定的數值+ (SCNAction *)fadeOpacityTo:(CGFloat)opacity duration:(NSTimeInterval)sec//將node 的opacity 漸漸層化到特定的數值+ (SCNAction *)hide// 隱藏node+ (SCNAction *)unhide//顯示node+ (SCNAction *)removeFromParentNode//移除node+ (SCNAction *)playAudioSource:(SCNAudioSource *)source waitForCompletion:(BOOL)wait//播放音頻。 waitForCompletion,BOOL值,//如果為YES Action的duration就是音訊時間長度;//如果為NO,可以認為duration 為0。 //可以去看SCNAudioPlayer 的API.+ (SCNAction *)group:(NSArray<SCNAction *> *)actions//group 被用來並發執行多個SCNAction+ (SCNAction *)sequence:(NSArray<SCNAction *> *)actions//順序執行多個SCNAction,上個SCNAction執行結束後,才執行下個SCNAction+ (SCNAction *)repeatAction:(SCNAction *)action count:(NSUInteger)count//將一個SCNAction執行count 次+ (SCNAction *)repeatActionForever:(SCNAction *)action// 一直執行某個SCNAction+ (SCNAction *)waitForDuration:(NSTimeInterval)sec//延遲SCNAction,比如用sequence 順序執行多個SCNAction時,//可以給SCNAction a,c 中間添加一個SCNAction b, //等a執行結束後,延遲一會,再去執行c+ (SCNAction *)runBlock:(void (^)(SCNNode *node))block//自訂SCNAction ,你可以在block 做一些操作+ (SCNAction *)runBlock:(void (^)(SCNNode *node))block queue:(dispatch_queue_t)queue//在一個特定的隊列中,執行block+ (SCNAction *)customActionWithDuration:(NSTimeInterval)seconds actionBlock:(void (^)(SCNNode *node, CGFloat elapsedTime))block//上篇數學旋轉用到的方法,當這個SCNAction執行時,//SceneKit 在這個時間間隔內會重複調用actionBlock,//並將已逝去的時間傳給actionBlock+ (SCNAction *)javaScriptActionWithScript:(NSString *)script duration:(NSTimeInterval)seconds//在時間間隔內,執行一段JavaScript代碼- (SCNAction *)reversedAction//逆轉一個已經建立的SCNAction,很好理解,//相當於CABasicAnimation的autoreverses屬性。哪裡來的,回哪裡去。@property(nonatomic) NSTimeInterval duration//SCNAction 的屬性,時間間隔,真即時間間隔受speed影響@property(nonatomic) CGFloat speed//SCNAction 的屬性,速度係數。假設duration 為10,但speed 為2的話,//就是速度是以前的2倍,實際duration 就為5@property(nonatomic) SCNActionTimingMode timingMode//SCNAction 的屬性,定時模式,有四個常量值:ConstantsSCNActionTimingModeLinear//勻速SCNActionTimingModeEaseIn//一開始慢,慢慢加快SCNActionTimingModeEaseOut//一開始快,逐漸層慢SCNActionTimingModeEaseInEaseOut//開始慢慢地,通過中間的時候加速,然後再次放緩
OK,瞭解過SCNAction的API後,我們就可以解決上一篇的問題了:添加一艘飛船,讓它繞著與x軸成45度的方向做圓周運動。
用到的API :
+ (SCNAction *)rotateByAngle:(CGFloat)angle aroundAxis:(SCNVector3)axis duration:(NSTimeInterval)duration
最終實現效果:
代碼全在demo裡面,感興趣的同學可以下載
https://github.com/pzhtpf/SceneKitRoationDemo
ios 3D引擎 SceneKit 開發(6) --SCNAction