KeyFrameAnimation
來源于動畫產(chǎn)業(yè),最早做動畫片的時候,會分為幾個角色像吻,牛點(diǎn)的人會根據(jù)劇情等因素把場景中的關(guān)鍵畫面畫出來峻黍,剩下的不那么牛的人則根據(jù)這些關(guān)鍵畫面把一些過渡性的圖片補(bǔ)足,假設(shè)一秒需要20張圖片拨匆,關(guān)鍵圖片可能有5張姆涩,剩下的15張則根據(jù)這5張的內(nèi)容來補(bǔ)齊,這就是最早的key frame的來源惭每。其實(shí)在視頻編解碼中也經(jīng)常會碰到類似的屬于阵面,比如KeyFrame和I幀P幀這些名詞,都是跟這些有關(guān)的洪鸭。
在iOS中,如果你使用CAKeyFrameAnimation
仑扑,則需要提供一些關(guān)鍵點(diǎn)览爵,然后iOS在顯示的過程中會根據(jù)這些信息自動補(bǔ)齊過渡性的內(nèi)容。
我們可以用下面一個飛機(jī)飛行線路的例子來說明
- (void)drawSpaceCurve
{
// Create a path
UIBezierPath *bezierPath = [[UIBezierPath alloc] init];
[bezierPath moveToPoint:CGPointMake(0, 150)];
[bezierPath addCurveToPoint:CGPointMake(300, 150)
controlPoint1:CGPointMake(75, 0)
controlPoint2:CGPointMake(225, 300)];
// Draw the path using CAShapeLayer
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.path = bezierPath.CGPath;
pathLayer.fillColor = [UIColor clearColor].CGColor;
pathLayer.strokeColor = [UIColor redColor].CGColor;
pathLayer.lineWidth = 3.0f;
[self.view.layer addSublayer:pathLayer];
// Add the ship
CALayer *shipLayer = [CALayer layer];
shipLayer.frame = CGRectMake(0, 0, 64, 64);
shipLayer.position = CGPointMake(0, 150);
shipLayer.contents = (__bridge id)[UIImage imageNamed:@"Ship"].CGImage;
[self.view.layer addSublayer:shipLayer];
// Create the keyframe animation
CAKeyframeAnimation *animation = [CAKeyframeAnimation animation];
animation.keyPath = @"position";
animation.duration = 4.0f;
animation.path = bezierPath.CGPath;
[shipLayer addAnimation:animation forKey:nil];
}
在代碼運(yùn)行中镇饮,我們確實(shí)看到了飛機(jī)的運(yùn)行軌跡和我們定義的bezierPath一致蜓竹,但有個問題,就是飛機(jī)的機(jī)頭方向沒有在運(yùn)行過程中做調(diào)整储藐,這便使動畫看起來怪怪的俱济,不過好在Apple已經(jīng)預(yù)見到這個需求,所以在CAKeyFrameAnimation中
提供了一個名為rotationMode
的屬性钙勃,當(dāng)我們把這個屬性設(shè)置為kCAAnimationRotateAuto
時蛛碌,飛機(jī)在運(yùn)行過程中機(jī)頭始終超前,實(shí)現(xiàn)了我們的需求辖源。
animation.rotationMode = kCAAnimationRotateAuto;
另外在實(shí)際的動畫應(yīng)用中蔚携,我們經(jīng)常會使用到多個動畫效果一同展示的情況,這種情況我們可以通過CAAnimationGroup
來實(shí)現(xiàn)克饶,它的用法和單獨(dú)設(shè)置一個動畫的效果沒有太大的區(qū)別酝蜒,但當(dāng)你把多種效果組合到一起,在展示的時候矾湃,就可以輕松完成多個效果的同時展示亡脑。
我們還是用上面的軌跡來演示,不過把飛機(jī)換成了一個色塊邀跃,動畫是使色塊不但按照我們規(guī)定好的路徑運(yùn)動霉咨,并且在運(yùn)動中進(jìn)行顏色的變換。
- (void)testAnimationGroup
{
UIBezierPath *bezierPath = [[UIBezierPath alloc] init];
[bezierPath moveToPoint:CGPointMake(0, 150)];
[bezierPath addCurveToPoint:CGPointMake(300, 150)
controlPoint1:CGPointMake(75, 0)
controlPoint2:CGPointMake(225, 300)];
CAShapeLayer *pathLayer = [CAShapeLayer layer];
pathLayer.path = bezierPath.CGPath;
pathLayer.fillColor = [UIColor clearColor].CGColor;
pathLayer.strokeColor = [UIColor redColor].CGColor;
pathLayer.lineWidth = 3.0f;
[self.view.layer addSublayer:pathLayer];
CALayer *colorLayer = [CALayer layer];
colorLayer.frame = CGRectMake(0, 0, 64, 64);
colorLayer.position = CGPointMake(0, 150);
colorLayer.backgroundColor = [UIColor greenColor].CGColor;
[self.view.layer addSublayer:colorLayer];
CAKeyframeAnimation *animation1 = [CAKeyframeAnimation animation];
animation1.keyPath = @"position";
animation1.path = bezierPath.CGPath;
animation1.rotationMode = kCAAnimationRotateAuto;
CABasicAnimation *animation2 = [CABasicAnimation animation];
animation2.keyPath = @"backgroundColor";
animation2.toValue = (__bridge id)[UIColor redColor].CGColor;
CAAnimationGroup *group = [CAAnimationGroup animation];
group.animations = @[animation1, animation2];
group.duration = 4.0f;
[colorLayer addAnimation:group forKey:nil];
}