你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> 淺談iOS如何做彈幕

淺談iOS如何做彈幕

編輯:IOS開發綜合

iOS彈幕demo網上有很多,而且大多數是開源的,很多源代碼我們可以自己查看。

彈幕有哪些特點呢?

最基本的特點:

1、文字越長的彈幕,跑的越快,彈幕的速度和文字長度有關系。

2、彈幕不相互碰撞。

3、如果有數據,會一條接著一跳的播放。

基於以上的基本特點,我們可以很簡單的想到iOS中可以實現的方式:

1、在view中一貞一貞的draw

2、用系統的動畫去做

上面一種柔性很強,可是對編程功底要求比較高,搞不好又影響了性能,還做不出好的效果。

下面一種很簡單,只需要動畫做好分段,處理好動畫間的銜接就可以了;可是柔性相對較差一點。

這裡采用系統動畫來做,這樣我們只需要做好下面幾個方面就OK了:

1、重用或者釋放;

2、暫停和繼續;

3、load新數據;

4、碰撞問題;

這裡簡單的貼一下思路,希望能為各位敞開一扇門。

首先我們做一個單獨的帶動畫的視圖,作為我們的彈幕基本試圖,後面我們只需要把這些試圖組合起來就成為我們想要的彈幕了。

 

@interface BulletView : UIView

@property (nonatomic, copy) void(^moveBlock)(CommentMoveStatus status);//狀態回調的block

@property (nonatomic, assign) NSInteger trajectory;//所在軌道編號

- (instancetype)initWithCommentDic:(BulletSettingDic *)commentDic;//這裡的BulletSettingDic是一個自定義的類,裡面主要設置了我們彈幕的背景顏色、文字顏色、字體、速率等

- (void)reloadDataWithDic:(BulletSettingDic *)reloadDic;//寫這個方法方便重用

- (void)startAnimation;

- (void)stopAnimation;

- (void)pauseAnimation;

- (void)resumeAnimation;

@end

 

CommentMoveStatus是一個枚舉集合,裡面設置了動畫的幾種狀態:

 

typedef NS_ENUM(NSInteger, CommentMoveStatus)
{
    MoveIn,
    Enter,
    MoveOut
};

BulletSettingDic是一個設置類,裡面給出了彈幕視圖的各種設置參數,頭文件如下:

 

這個裡面的內容,我們可以隨便自定義,然後修改寫入視圖就好了。

 

@interface BulletSettingDic : NSObject
{
    NSMutableDictionary *_settingDic;
}
//設置字顏色
-(void)setBulletTextColor:(UIColor *)color;
-(UIColor *)bulletTextColor;

//設置背景顏色
-(void)setBulletBackgroundColor:(UIColor *)color;
-(UIColor *)bulletBackgroundColor;

//設置字體
-(void)setBulletTextFont:(UIFont *)font;
-(UIFont *)bulletTextFont;

//設置內容
-(void)setbulletText:(NSString *)text;
-(NSString *)bulletText;

//設置高度
-(void)setBulletHeight:(CGFloat)height;
-(CGFloat)bulletHeight;

//設置動畫時長
-(void)setBulletAnimationDuration:(float)duration;
-(float)bulletAnimationDuration;

//設置速度比率
-(void)setBulletAnimationSpeedRate:(float)speedRate;
-(float)bulletAnimationSpeedRate;

-(NSMutableDictionary *)settingDic;@end

 

下面是核心思路:

 

//開始動畫
- (void)startAnimation
{
    __block CGRect frame = self.frame;
    __unsafe_unretained typeof(self)weakSelf = self;
    
    //計算移動的時間
    CGFloat dur = (CGRectGetMinX(frame)-_screenWidth)/_real_speed;
    
    [UIView animateWithDuration:dur delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
        frame.origin.x = _screenWidth;
        weakSelf.frame = frame;
    } completion:^(BOOL finished)
     {
         [weakSelf.layer removeAllAnimations];
         //彈幕開始進入屏幕
        if (weakSelf.moveBlock)
            weakSelf.moveBlock(MoveIn);
         [weakSelf beginMoveIn];
     }];
}
//開始移入-->完全進入
-(void)beginMoveIn
{
    __block CGRect frame = self.frame;
    __unsafe_unretained typeof(self)weakSelf = self;
    
    //計算移動的時間
    CGFloat dur = CGRectGetWidth(frame)/_real_speed;
    
    [UIView animateWithDuration:dur delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
        frame.origin.x = _screenWidth-CGRectGetWidth(frame);
        weakSelf.frame = frame;
    } completion:^(BOOL finished)
     {
         [weakSelf.layer removeAllAnimations];
         //彈幕完全進入屏幕
         if (weakSelf.moveBlock)
             weakSelf.moveBlock(Enter);
         [weakSelf enterIn];
     }];
}
//完全進入-->完全移出
-(void)enterIn
{
    __block CGRect frame = self.frame;
    __unsafe_unretained typeof(self)weakSelf = self;
    
    CGFloat dur = _screenWidth/_real_speed;
    
    [UIView animateWithDuration:dur delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
        frame.origin.x = -CGRectGetWidth(frame);
        weakSelf.frame = frame;
    } completion:^(BOOL finished)
     {
         //彈幕完全離開屏幕
         if (weakSelf.moveBlock)
             weakSelf.moveBlock(MoveOut);
         [weakSelf.layer removeAllAnimations];
         [weakSelf removeFromSuperview];
     }];
}
這裡面,我做了三段動畫:開始-->移入,移入-->完全移入,完全移入-->完全移出,然後每一個完成後都會有相應的block回調出去(這樣做是為了方便我們根據狀態進行數據和視圖的處理,下面會用到)。

 

_real_speed是動畫移動的實際速度,它是由動畫移動的速度率和速度相乘得到的,動畫的速度是通過屏幕寬度和文本寬度以及動畫時間計算得到的,速度率是設置的。

關於暫停和繼續,我使用CALayer裡面與CAMediaTimming相關的方法,改變速度,紀錄時間,做到的。代碼如下:

 

//暫停動畫
- (void)pauseAnimation
{
    CALayer *layer = self.layer;
    layer.fillMode = kCAFillModeForwards;
    CFTimeInterval pausedTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
    layer.speed = 0.0;
    layer.timeOffset = pausedTime;
}

//繼續動畫
- (void)resumeAnimation
{
    CALayer*layer = self.layer;
    CFTimeInterval pausedTime = [layer timeOffset];
    layer.speed = 1.0;
    layer.timeOffset = 0.0;
    layer.beginTime = 0.0;
    CFTimeInterval timeSincePause = [layer convertTime:CACurrentMediaTime() fromLayer:nil] - pausedTime;
    layer.beginTime = timeSincePause;
}
停止和開始就不詳述了。

 

下面說視圖的重用,我用了兩個數組來做視圖的重用,當有彈幕視圖移出屏幕的時候我會把移出的視圖保存在一個數組中。

在下一個視圖制作的時候,直接設置取出來重新加載數據,而不是重新創建對象。

核心操作很簡單:

 

if (_reuseableBulletArray.count)
    {
        view = [_reuseableBulletArray firstObject];
        [view reloadDataWithDic:_bulletDic];
        [_reuseableBulletArray removeObjectAtIndex:0];
    }else
    {
        view = [[BulletView alloc] initWithCommentDic:_bulletDic];
    }[_bulletArray addObject:view];

 

 

然後在合適的地方(一般是有彈幕視圖移出屏幕的地方):

 

[_bulletArray removeObject:weakBulletView];
[_reuseableBulletArray addObject:weakBulletView];

這樣就可以不用創建很多的對象了。

 

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