你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> 直播APP常用動畫效果

直播APP常用動畫效果

編輯:IOS開發基礎

介紹

記錄、總結開發遇到一些問題,大家一起交流學習。
這次帶來,對直播APP的常用動畫總結。

效果展示

下面是一個很多平台都有的入門豪華禮物動畫——煙花。
一個復雜的禮物動畫,首先是美術給出gif實現草圖素材,技術進行動畫剖析圖片壓縮,在程序中加載圖片實現動畫,其中要注意內存和CPU占用

1049769-221dd23d872547bf.gif

圖片壓縮、加載與裁剪

1、圖片壓縮

美術給出的圖片,即使是壓縮過,仍存在較大的壓縮空間,可以用這裡或者更好的大小優化。

2、圖片加載

主要有-imageNamed:-imageWithContentsOfFile:兩種方式。
AnimationImageCache類是一個動畫圖片加載類,用單例實現且內部用NSCache持有引用。

注意,當收到內存不足警告時,NSCache會自動釋放內存。所以每次訪問NSCache,即使上一次已經加載過,也需要判斷返回值是否為空。

3、圖片裁剪

為了減少圖片資源的大小,有時候會把多個幀動畫做成連續的一張圖。這時需要程序加載一整張資源圖,並在相應的位置進行裁剪。

    UIImage* sourceImage = [UIImage imageNamed:@"image/animation/gift_boat"];
    CGSize sourceSize = sourceImage.size;
    CGImageRef cgimage = CGImageCreateWithImageInRect(sourceImage.CGImage,
                                                      CGRectMake(0, 0, const_position_boat_x, sourceSize.height));
    gWaveFrameImage = [UIImage imageWithCGImage:cgimage];
    CGImageRelease(cgimage);
    cgimage = CGImageCreateWithImageInRect(sourceImage.CGImage,
                                           CGRectMake(const_position_boat_x, 0, const_position_boat_width, sourceSize.height));
    gBoatFrameImage = [UIImage imageWithCGImage:cgimage];
    CGImageRelease(cgimage);
    cgimage = CGImageCreateWithImageInRect(sourceImage.CGImage,
                                           CGRectMake(const_position_boat_x + const_position_boat_width, 0, sourceSize.width - const_position_boat_x - const_position_boat_width, sourceSize.height));
    gShadowFrameImage = [UIImage imageWithCGImage:cgimage];
    CGImageRelease(cgimage);

動畫剖析與時間軸

下面這個是一個全屏類型的“天使”禮物動畫,我們來剖析下這個動畫的構成。

  • 1、背景變暗,出現星空;

  • 2、流星劃過、月亮出現、雲彩飄動;

  • 3、兩側浮空島震動,中間浮空島出現;

  • 4、背光出現,天使落下,翅膀扇動;

  • 5、星星閃爍、鳳凰出現;

  • 6、漸隱消失;

時間軸實現

為了讓動畫按照時間順序一一執行,可以把動畫按時間和對象分成多個方法,通過GCD在指定的時間調用。

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self playMeteorAnimation];
    });

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self playLandAnimation];
    });

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(6.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self playLightAnimation];
    });

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(7.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        [self playStarAnimation];
    });

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(TOTAL_TIME * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
        @weakify(self);
        [UIView animateWithDuration:0.5 animations:^{
            self.alpha = 0;
        } completion:^(BOOL finished) {
            @strongify(self);
            [self removeFromSuperview];
            [self callBackManager];
        }];
    });

常用動畫效果

1、視圖變暗、變大

alpha值屬性是透明度,把背景設置成淡黑色,然後調整alpha可以達到背景漸變的視圖效果;
UIView的transform是可以用仿射變換矩陣來控制平移、放大縮小等。

    [UIView animateWithDuration:1.5 animations:^{
        self.mBackgroundView.alpha = 0.5;
        self.mAngelView.transform = CGAffineTransformMakeScale(1.2, 1.2);
    }];

2、勻速運動、交錯效果

right是項目封裝的一個屬性,本質是對UIView的frame進行操作;
兩朵雲, 左邊的朝右,右邊的朝左,即可達到交錯的效果。

    [UIView animateWithDuration:TOTAL_TIME delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
        self.mAngelCloudView0.right += 250;
        self.mAngelCloudView1.right -= 190;
    } completion:nil];

3、上下往返運動

CAKeyframeAnimation是關鍵幀動畫,對layer的postion的y坐標進行操作;
設定好起始位置、經過位置,最後回到起始位置,即可實現上下往返的效果。

    CAKeyframeAnimation *upDownAnimation;
    upDownAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position.y"];
    upDownAnimation.values = @[@(self.mAngelLandView1.layer.position.y), @(self.mAngelLandView1.layer.position.y + 5), @(self.mAngelLandView1.layer.position.y)];
    upDownAnimation.duration = 2;
    upDownAnimation.fillMode = kCAFillModeBoth;
    upDownAnimation.calculationMode = kCAAnimationCubic;
    upDownAnimation.repeatCount = HUGE_VALF;
    [self.mAngelLandView1.layer addAnimation:upDownAnimation forKey:@"upDownAnimation"];

4、閃爍效果

閃爍的本質是alpha的變化,但是UIView的block動畫不好實現重復效果;
UIView的alpha對應的是layer的opacity屬性,設定好起始、過度和結束的狀態,實現閃爍的效果。

    CAKeyframeAnimation *opacityAnimation;
    opacityAnimation = [CAKeyframeAnimation animationWithKeyPath:@"opacity"];
    opacityAnimation.values = @[@(0), @(1), @(0)];
    opacityAnimation.duration = 1.5;
    opacityAnimation.fillMode = kCAFillModeBoth;
    opacityAnimation.calculationMode = kCAAnimationCubic;
    opacityAnimation.repeatCount = HUGE_VALF;
    [self.mAngelStarView.layer addAnimation:opacityAnimation forKey:@"opacityAnimation"];

5、貝塞爾曲線運動

貝塞爾曲線是優化動畫體驗的很重要部分,比如說天上掉下來的羽毛,地上冒起來的氣泡,空中飄蕩的氣球,都可以用貝塞爾曲線來繪制,從而獲得很好的視覺體驗;
本質還是關鍵幀動畫,這次操作的屬性是position,通過path屬性來確定路徑;
給貝塞爾曲線設定好目標點後,把path賦值給關鍵幀動畫,再把動畫添加到layer上即可;

    UIImage *image = [[AnimationImageCache shareInstance] getImageWithName:@"gift_castle_hot_air_balloon3.png"];
    UIImageView *hotAirBalloonView0 = [[UIImageView alloc] initWithFrame:CGRectMake(50, 100, image.size.width / 2, image.size.height / 2)];
    [self addSubview:hotAirBalloonView0];
    [hotAirBalloonView0 setImage:image];
    // 飄動
    CGPoint position = CGPointMake(self.width, hotAirBalloonView0.top);
    CGFloat duration = 5;
    CAKeyframeAnimation *positionAnimate = [CAKeyframeAnimation animationWithKeyPath:@"position"];
    positionAnimate.repeatCount = 1;
    positionAnimate.duration = duration;
    positionAnimate.fillMode = kCAFillModeForwards;
    positionAnimate.removedOnCompletion = NO;
    UIBezierPath *sPath = [UIBezierPath bezierPath];
    [sPath moveToPoint:position];
    [sPath addCurveToPoint:CGPointMake(-image.size.width / 2, position.y) controlPoint1:CGPointMake(self.width / 3 * 2, position.y - 60) controlPoint2:CGPointMake(self.width / 3, position.y + 60)];
    positionAnimate.path = sPath.CGPath;
    [hotAirBalloonView0.layer addAnimation:positionAnimate forKey:@"positionAnimate"];

6、遮罩動畫

遮罩效果可以實現彩虹出現、煙花爆炸、畫卷打開等效果,通過改變遮罩的大小,影響原始圖片的展示,達到動畫的效果;
先新建一個CAShapeLayer,並設置為layer的遮罩;
新建一個動畫,設定初始和結束狀態並賦值給CAShapeLayer,完成一個遮罩動畫。

    UIBezierPath *maskStartPath = [UIBezierPath bezierPathWithRect:CGRectMake(CGRectGetWidth(rainbowView1.bounds), 0, CGRectGetWidth(rainbowView1.bounds), CGRectGetHeight(rainbowView1.bounds))];
    UIBezierPath *maskFinalPath = [UIBezierPath bezierPathWithRect:rainbowView1.bounds];
    CAShapeLayer *maskLayer = [CAShapeLayer layer];
    rainbowView1.layer.mask = maskLayer;
    maskLayer.path = maskFinalPath.CGPath;
    CABasicAnimation *maskLayerAnimation = [CABasicAnimation animationWithKeyPath:@"path"];
    maskLayerAnimation.fromValue = (__bridge id)maskStartPath.CGPath;
    maskLayerAnimation.toValue = (__bridge id)maskFinalPath.CGPath;
    maskLayerAnimation.removedOnCompletion = NO;
    maskLayerAnimation.duration = 2.0;
    maskLayerAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
    [maskLayer addAnimation:maskLayerAnimation forKey:@"maskLayerAnimation"];

7、旋轉效果

燈光掃動,花朵旋轉等旋轉效果,都可以transform的rotation.z屬性來實現;
同樣使用CAKeyframeAnimation實現,設定好初始、中間、結束狀態,動畫時間已經重復次數,並添加到layer,完成旋轉效果;

    CAKeyframeAnimation* rotationAnimation;
    rotationAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform.rotation.z"];
    rotationAnimation.values = @[@(M_PI / 12), @(M_PI / 3), @(M_PI / 12)];
    rotationAnimation.duration = 2.5;
    rotationAnimation.fillMode = kCAFillModeBoth;
    rotationAnimation.calculationMode = kCAAnimationCubic;
    //    rotationAnimation.cumulative = YES;
    rotationAnimation.repeatCount = HUGE_VALF;

    [self.mLightLeftView.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];

8、幀動畫

某些復雜動畫不是靠對原始圖像操作進行操作就能實現,這時候就要用到幀動畫
幀動畫有兩種實現方式,一種是通過Timer(定時器),設定好時間間隔,手動替換圖片;
另外一種是通過UIImageView的支持,實現幀動畫。

UIImageView的幀動畫沒有回調,如果需要實現達到第幾幀之後,開始另外的動畫的效果,需要用第一種方法。

    NSMutableArray *images = [NSMutableArray array];
    for (int i = 0; i < 6; ++i) {
        UIImage *img = [[AnimationImageCache shareInstance] getDriveImageWithName:[NSString stringWithFormat:@"gift_animation_angel_phoenix%d.png", i]];
        if (img) {
            [images addObject:img];
        }
    }
    self.mAngelPhoenixView.image = [[AnimationImageCache shareInstance] getDriveImageWithName:@"gift_animation_angel_phoenix0.png"];
    self.mAngelPhoenixView.animationImages = images;
    self.mAngelPhoenixView.animationDuration = 0.8;
    self.mAngelPhoenixView.animationRepeatCount = 1;
    [self.mAngelPhoenixView startAnimating];

動畫的性能優化

直播APP的性能優化-禮物篇
iOS開發-視圖渲染與性能優化
都有,不再贅述。

總結

UIView的block動畫中,completion持有的是強引用,需要避免造成循環引用。

但在調用完畢completion後,會釋放引用。

天使動畫的圖片大小為900KB,運行時占內存15MB,播放完畢後,如果收到內存不足的警告會釋放內存;

煙花動畫的圖片大小為400KB,運行時占用的內存為20MB,播放完畢後,會馬上釋放內存;

思考題

1、為什麼煙花動畫的圖片大小比較小,運行時占用的內存反而更多?

2、播放完畢馬上釋放和收到內存不足警告再釋放,兩種圖片加載方式的優缺點?

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved