#import <UIKit/UIKit.h>
typedef NS_ENUM(NSInteger, MoveStatus) {
Start,
Enter,
End
};
@interface BulletView: UIView
@property (nonatomic, assign) int trajectory; //彈道
@property (nonatomic, copy) void(^moveStatusBlock)(MoveStatus status); // 彈幕狀態(tài)回調(diào)
//初始化彈幕
- (instancetype)initWithComment:(NSString*)comment;
//開始動畫
- (void)startAnimation;
//結(jié)束動畫
- (void)stopAnimation;
@end
#import "BulletView.h"
#define Padding 10;
#define PhotoHeight 30;
@interface BulletView ()
@property (nonatomic, strong) UILabel *lbComment;
@property (nonatomic, strong) UIImageView *photoIgv;
@end
@implementation BulletView
//初始化彈幕
- (instancetype)initWithComment:(NSString *)comment {
if (self = [super init]) {
self.backgroundColor = [UIColor redColor];
self.layer.cornerRadius = 15;
NSDictionary *attr = @{NSFontAttributeName:[UIFont systemFontOfSize:14]};
CGFloat width = [comment sizeWithAttribute:attr].width;
self.bounds = CGRectMake(0, 0, width + 2 * Padding + PhotoHeight, 30);
self.lbComment.text = comment;
self.lbcomment.frame = CGRectMake(Padding + PhotoHeight, 0, width, 30);
self.bphotoIgv.frame = CGRectMake(-Padding, -Padding, PhotoHeight + Padding, PhotoHeight + Padding);
self.layer.cornerRadius = () / 2;
self.photoIgv.layer.borderColor = [UIColor orangeColor].CGColor;
self.photoIgv.layer.borderWidath = 1;
self.photoIgv.img = [UIImage imageNamed:@""];
}
return self;
}
//開始動畫
- (void)startAnimation {
CGFloat screenWidth = [UIScreen mainScreen].bounds.size.width;
CGFloat duration = 4.f;
CGFloat wholeWidth = screenWidth + CGRectGetWidth(self.bounds);
//開始彈幕
if (self.moveStausBlock) {
self.moveStatusBlock(Start);
}
//t = s / v;
CGFloat speed = wholeWidth/duration;
CGFloat enterDuration = CGRectGetWidat(self.bounds)/speed;
/*
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(enterDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
if (self.moveStausBlock) {
self.moveStatusBlock(Enter);
}
});
*/
[self performSelector:@selector(enerScreen) withObject:nil afterDelay:enterDuration];
//[NSObject cancelPreviousPerformRequestsWithTarget:self];
__block CGRect frame = self.frame;
[UIView animateWithDuration:duration delay:0 options:UIViewAnimationOptionCurveLinear animations:^{
frame.origin.x -= wholeWidth;
self.frame = frame;
} completion:^(BOOL finished) {
[self removeFromSuperview];
if (self.moveStatusBlock) {
self.moveStatusBlock(End);
}
}];
}
- (void)enterScreen {
if (self.moveStatusBlock) {
self.moveStatusBlock(Enter);
}
}
//結(jié)束動畫
- (void)stopAnimation {
[NSObject cancelPreviousPerformRequestsWithTarget:self];
[self.layer removeAllAnimations];
[self removeFromSuperview];
}
- (UILabel *)lbComment {
if (!_lbComment) {
_lbComment = [[UILabel alloc] initWithFrame:CGRectZero];
_lbComment.font = [UIFont systemFontOfSize:14];
_lbComment.textColor = [UIColor whiteColor];
_lbComment.textAlignment = NSTextAlignmentCenter;
[self addSubview:_lbComment];
}
return _lbComment;
}
- (UIImageView *)photoIgv {
if (!_photoIgv) {
_photoIgv = [[UIImageView alloc] init];
_photoIgv.layer.masksToBounds = YES;
_hotoIgv.contentMode = UIViewContentModeScaleAspectFill;
[self addSubview:_hotoIgv];
}
return bphotoIgv;
}
@end
#import <Foundation/Foundation.h>
@class BulletView;
@interface BulletManager: NSObject
@property (nonatomic, copy) void(^generateViewBlock)(BulletView *view);
- (void)start;
- (void)stop;
@end
#import "BulletManager.h"
#import "BulletView.h"
@interface BulletManager ()
//彈幕的數(shù)據(jù)來源
@property (nonatomic, strong) NSMutableArray *datasource;
//彈幕使用過程中的數(shù)組變量
@property (nonatomic, strong) NSMutableArray *bulletComments;
//存儲彈幕view的數(shù)組變量
@property (nonatomic, strong) NSMutableArray *bulletViews;
@property (nonatomic, assign) BOOL bStopAnimation;
@end
@implementation BulletManager
- (void)start {
[self.bulletComments removeAllObjects];
[self.bulletComments addObjectsFromArray:self.datasource];
[self initBulletComment];
}
- (void)stop {
if (self.bStopAnimation) {
return;
}
self.bStopAnimation = YES;
[self.bulletViews enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonull stop){
BulletView *view = obj;
[view stopAnimation];
view = nil;
}];
[self.bulletViews removeAllObjects];
}
//初始化彈幕,隨即分配彈幕軌跡
- (void)initBulletComment {
NSMutableArray *trajectorys = [NSMutableArray arrayWithArray:@[@0, @1, @2]];
for (int i = 0; i < 3; i++) {
if (self.bulletComments.count > 0) {
//隨即獲取彈幕的軌跡
NSInteger index = arc4random() % trajectorys.count;
int trajectory = [trajectorys[index] intValue];
//從彈幕數(shù)組逐一取出彈幕數(shù)據(jù)
NSString *comment = [self.bulletComments firstObject];
[self.bulletComments removeObjectAtIndex:0];
//創(chuàng)建彈幕
[self createBulletView:comment trajectory:trajectory];
}
}
}
- (void)createBulletView:(NSString *)comment tragectory:(int)trajectory {
if (self.bStopAnimation) { return; }
BulletView *view = [[BulletView alloc] initWithComment:comment];
view.trajectory = trajectory;
__weak typeof (view) weakView = view;
__weak typeof (self) weakSelf = self;
view.moveStatusBlock = ^(MoveStatus status){
if (self.bStopAnimation) { return; }
switch (status) {
case Start: {
[weakSelf.bulletViews addObject:weakView];
break;
}
case Enter: {
//判斷是否有其余彈幕
NSString *comment = [weakSelf nextComment];
if (comment) {
[weakSelf createBulletView:comment trajectory:trajectory];
}
break;
}
case End: {
if([weakSelf.bulletViews containsObject:weakView]) {
//飛出釋放資源
[weakView stopAnimation];
[weakSelf.bulletViews removeObject:weakView];
}
if (weakSelf.bulletViews.count == 0) {
//屏幕無彈幕 開始循環(huán)
self.bStopAnimation = YES;
[weakSelf start];
}
break;
}
default: break;
}
// [weakView stopAnimation];
// [weakSelf.bulletViews removeObject:weakView];
};
if (self.generateViewBlock) {
self.generateViewBlock(weakView);
}
}
- (NSString *)nextComment {
if (self.bulletComments.count == 0) {
return nil;
}
NSString *comment = [self.bulletComments firstObject];
if (comment) {
[self.bulletComments removeObjectAtIndex:0];
}
return comment;
}
- (NSMutableArray *)datasource {
if (!_datasource) {
_datasource = [NSMutableArray arrayWithArray:@[@"測試1", @"測試2", @"測試3", @"測試4", @"測試5", @"測試6", @"測試7", @"測試8"]];
}
return _datasource;
}
- (NSMutableArray *)bulletComments {
if (!_bulletComments) {
_bulletComments = [NSMutableArray array];
}
return _bulletComments;
}
- (NSMutableArray *)bulletViews {
if (!_bulletViews) {
_bulletViews = [NSMutableArray array];
}
return _bulletViews;
}
@end
//某viewController
#import "BulletManager.h"
#import "BulletView.h"
@property (nonatomic, strong) BulletManager *manager;
- (void)viewDidLoad {
[super viewDidLoad];
self.manager = [[BulletManager alloc] init];
__weak typeof(self) weakSelf = self;
self.manager.generateViewBlock = ^(BulletView *view) {
[weakSelf addSubview:view];
};
UIButton *btn = [UIButton buttonWithType:UIButtonTypeCustom];
[btn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[btn setTitle:@"start" forState:UIControlStateNormal];
btn.frame = CGRectMake(100, 100, 100, 40);
[btn addTarget:self action:@selector(clickBtn) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
[btn setTitleColor:[UIColor blueColor] forState:UIControlStateNormal];
[btn setTitle:@"stop" forState:UIControlStateNormal];
btn.frame = CGRectMake(250, 100, 100, 40);
[btn addTarget:self action:@selector(clickStopBtn) forControlEvents:UIControlEventTouchUpInside];
[self.view addSubview:btn];
}
- (void)clickBtn {
[self.manager start];
}
- (void)clickStopBtn {
[self.manager stop];
}
- (void)addBulletView:(BulletView *)view {
CGFloat widath = [UIScreen mainScreen].bounds.size.width;
view.frame = CGRectMake(width, 300 + view.trajectory * 50, CGRectGetWidth(view.bounds), CGRectGetHeight(view.bounds));
[self.view addSubview:view];
[view startAnimation];
}
彈幕相關(guān)代碼
最后編輯于 :
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
- 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來尤揣,“玉大人搔啊,你說我怎么就攤上這事”毕罚” “怎么了负芋?”我有些...
- 文/不壞的土叔 我叫張陵,是天一觀的道長嗜愈。 經(jīng)常有香客問我旧蛾,道長,這世上最難降的妖魔是什么蠕嫁? 我笑而不...
- 正文 為了忘掉前任锨天,我火速辦了婚禮,結(jié)果婚禮上剃毒,老公的妹妹穿的比我還像新娘病袄。我一直安慰自己稿壁,他們只是感情好琉雳,可當(dāng)我...
- 文/花漫 我一把揭開白布戒傻。 她就那樣靜靜地躺著纸泄,像睡著了一般。 火紅的嫁衣襯著肌膚如雪幅慌。 梳的紋絲不亂的頭發(fā)上宋欺,一...
- 文/蒼蘭香墨 我猛地睜開眼菩咨,長吁一口氣:“原來是場噩夢啊……” “哼吠式!你這毒婦竟也來了陡厘?” 一聲冷哼從身側(cè)響起抽米,我...
- 正文 年R本政府宣布戏罢,位于F島的核電站屋谭,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏龟糕。R本人自食惡果不足惜桐磁,卻給世界環(huán)境...
- 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望讲岁。 院中可真熱鬧我擂,春花似錦衬以、人聲如沸。這莊子的主人今日做“春日...
- 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至秧耗,卻和暖如春备籽,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背分井。 一陣腳步聲響...
推薦閱讀更多精彩內(nèi)容
- 警言:慎終如始承绸! 一,在布局文件中留好Fragment的位置(紅色區(qū)域)挣轨,這里可以用別的布局军熏,相對布局,線性布局都...
- 此文章單方面對 貝塞爾曲線畫圖 核心動畫 圖層相關(guān) 方面做下整理,方便查看! 概念簡介 (貝塞爾曲線)是應(yīng)用于二維...
- http://www.jb51.net/article/30317.htm import socketimport...
- 紀(jì)實生活 體悟人生 我在這里先做一下自己的介紹吧 簡單的就好 我叫木風(fēng)恒 木風(fēng)恒是一個六合卦之恒卦 我是從這而得如...