直播问题交流可加群 379258188
备注简书
之前写过直播间的礼物效果的文章
iOS开发 - Lottie实现直播间礼物特效
iOS开发-SVGA Animation实现直播间礼物特效
上面两篇只是对Lottie
和SVGA
的简单介绍
本次主要是结合我们上线直播项目对SVGA
的使用,直播间接收到礼物消息之后,礼物效果要依次展示!
主要方式是创建一个SvgaManager
,里面维护一个NSMutableArray
,数组里存放的是礼物的信息,等待一个动画执行完成之后,再执行下一个动画!
SVGAPlayer
创建SVGACustomPlayer
继承SVGAPlayer
,SVGAPlayer
本身是UIView
,重写下面的方法,让礼物效果不接受事件
/**
每个view都有这个方法,用来处理用户的操作事件。
@return 它返回:self,代表这个view会接受用户的操作事件,返回:nil,则代表这个view不会接受用户的操作事件。
*/
- (UIView *)hitTest:(CGPoint)point withEvent:(UIEvent *)event {
return nil;
}
SvgaManager
- SvgaManager.h
typedef NS_ENUM(NSInteger, SvgaMgrType)
{
SvgaMgrTypeGifts = 0, //类型礼物
SvgaMgrTypeMounts, //进场动画
};
@interface SvgaManager : NSObject
/**
单个动画循环次数
*/
@property (nonatomic, assign) NSInteger loops;
@property (nonatomic, assign) BOOL clearsAfterStop;
@property (nonatomic, assign) SvgaMgrType type;
@property (nonatomic, strong) SVGACustomPlayer *aPlayer; //Tag 礼物:0 座驾:1 用于区分
/**
添加svga动画 等待执行
@param model svga动画关联数据
*/
-(void)loadSvgaItem:(SvgaMgrModel *)model superview:(UIView *)view SVGAFrame:(CGRect)rect;
@end
- SvgaManager.m
@interface SvgaManager()<SVGAPlayerDelegate>
@property (nonatomic, assign)BOOL isPlay;
@property (nonatomic, strong) SVGAParser *aParser;
/**
存放需要执行的svga动画
*/
@property (nonatomic, strong) NSMutableArray<SvgaMgrModel *>* svgaItems;
@property (nonatomic, strong) UIView *tempSuperView;
// 是否是礼物操作
@property (nonatomic, assign) BOOL isGiftSvga;
// 是否是座驾操作
@property (nonatomic, assign) BOOL isMountsSvga;
@end
@implementation SvgaManager
- (instancetype)init {
if (self = [super init]) {
self.isGiftSvga = NO;
self.isMountsSvga = NO;
}
return self;
}
- (void)loadSvgaItem:(SvgaMgrModel *)model superview:(UIView *)view SVGAFrame:(CGRect)rect {
self.tempSuperView = view;
// 缓存数据
[self.svgaItems addObject:model];
if (self.type == SvgaMgrTypeMounts) { // 进场特效
[view addSubview:self.aPlayer];
[self aPlayerSet:rect];
}else{ // 礼物效果
// 根据需求,是否需要修改礼物图层顺序
for (UIView *svgaView in view.subviews) {
if ([svgaView isKindOfClass:[SVGAPlayer class]] && svgaView.tag == 1) { // 这里直播间存在进场特效
[view insertSubview:self.aPlayer belowSubview:svgaView];
[self aPlayerSet:rect];
return;
}
}
// 正常情况
[view addSubview:self.aPlayer];
[self aPlayerSet:rect];
}
}
- (void)aPlayerSet:(CGRect)rect{
self.aPlayer.frame = rect;
self.aPlayer.loops = (int)self.loops;
self.aPlayer.clearsAfterStop = self.clearsAfterStop;
if (self.isPlay != YES) {
[self playSvga];
}
}
#pragma mark - Private
- (void)playSvga {
if (self.svgaItems.count == 0 ) { //队列中不存在效果
return;
}
self.isPlay = YES;
__weak typeof(self) weakSelf = self;
SvgaMgrModel * model = self.svgaItems.firstObject;
// 执行动画
[self.aParser parseWithURL:[NSURL URLWithString:model.svgaUrl] completionBlock:^(SVGAVideoEntity * _Nullable videoItem) {
if (videoItem) {
weakSelf.aPlayer.videoItem = videoItem;
[weakSelf.aPlayer startAnimation];
self.isGiftSvga = YES;
if (self.type == SvgaMgrTypeMounts) { // 这里入场动画的文字特效
self.isMountsSvga = YES;
[self showMounstView:model];
}
if (weakSelf.svgaItems.count > 0) {
[weakSelf.svgaItems removeFirstObject];
}
}
} failureBlock:^(NSError * _Nullable error) {
}];
}
// 执行特效文字
- (void)showMounstView:(SvgaMgrModel *)model {
// TODO:
}
#pragma mark - <SVGAPlayerDelegate>
- (void)svgaPlayerDidFinishedAnimation:(SVGAPlayer *)player {
if (self.svgaItems.count == 0) {
[self.aPlayer removeFromSuperview];
self.isGiftSvga = NO;
if (self.isMountsSvga == NO && self.isGiftSvga == NO) {
self.isPlay = NO;
}
}else{
self.isGiftSvga = NO;
// if (self.type == SvgaMgrTypeGifts && self.isGiftSvga == NO) {
// [self playSvga];
// }else if (self.type == SvgaMgrTypeMounts && self.isMountsSvga == NO){
// [self playSvga];
// }
if (self.isMountsSvga == NO && self.isGiftSvga == NO) {
[self playSvga];
}
}
}
- (void)dealloc{
DLog(@"内存已经释放");
}
#pragma mark - setter/getter
- (SVGACustomPlayer *)aPlayer {
if (_aPlayer == nil) {
_aPlayer = [[SVGACustomPlayer alloc] init];
_aPlayer.delegate = self;
_aPlayer.contentMode = UIViewContentModeScaleAspectFit;
}
return _aPlayer;
}
- (SVGAParser *)aParser{
if (_aParser == nil) {
_aParser = [[SVGAParser alloc]init];
}
return _aParser;
}
- (NSMutableArray<SvgaMgrModel *> *)svgaItems {
if (_svgaItems == nil) {
_svgaItems = [NSMutableArray array];
}
return _svgaItems;
}
@end
上述的SvgaManager
也对进场特效进行的出去
如何使用:
懒加载Manager
- (SvgaManager *)giftSvgaManager {
if (_giftSvgaManager == nil) {
_giftSvgaManager = [[SvgaManager alloc]init];
_giftSvgaManager.type = SvgaMgrTypeGifts;
_giftSvgaManager.aPlayer.tag = 0;
_giftSvgaManager.clearsAfterStop = YES;
_giftSvgaManager.loops = 1;
}
return _giftSvgaManager;
}
接收到消息的时候
// model中还有其他的属性,比如用户信息用于进场动画
SvgaMgrModel *model = [[SvgaMgrModel alloc]init];
model.svgaUrl = @"";
[self.giftSvgaManager loadSvgaItem:model superview:self.view SVGAFrame:self.view.frame];
模拟一下礼物消息
NSArray *items = @[
@"https://github.com/yyued/SVGA-Samples/blob/master/EmptyState.svga?raw=true",
@"https://github.com/yyued/SVGA-Samples/blob/master/HamburgerArrow.svga?raw=true",
@"https://github.com/yyued/SVGA-Samples/blob/master/PinJump.svga?raw=true",
@"https://github.com/yyued/SVGA-Samples/blob/master/TwitterHeart.svga?raw=true",
@"https://github.com/yyued/SVGA-Samples/blob/master/Walkthrough.svga?raw=true",
@"https://github.com/yyued/SVGA-Samples/blob/master/angel.svga?raw=true",
@"https://github.com/yyued/SVGA-Samples/blob/master/halloween.svga?raw=true",
@"https://github.com/yyued/SVGA-Samples/blob/master/kingset.svga?raw=true",
@"https://github.com/yyued/SVGA-Samples/blob/master/posche.svga?raw=true",
@"https://github.com/yyued/SVGA-Samples/blob/master/rose.svga?raw=true",
];
SvgaMgrModel *model = [[SvgaMgrModel alloc]init];
model.svgaUrl = items[arc4random() % 10];
[self.giftSvgaManager loadSvgaItem:model superview:self.view SVGAFrame:self.view.frame];
本文demo https://github.com/TsuiOS/HsuLive
上面的SVGA文件是存放再github上的,访问很慢! 我在七牛上也上传了一份,加载速度明显提升
http://phq4iiqb5.bkt.clouddn.com/HamburgerArrow.svga
http://phq4iiqb5.bkt.clouddn.com/Walkthrough.svga
http://phq4iiqb5.bkt.clouddn.com/PinJump.svga
http://phq4iiqb5.bkt.clouddn.com/EmptyState.svga
http://phq4iiqb5.bkt.clouddn.com/heartbeat.svga
http://phq4iiqb5.bkt.clouddn.com/halloween.svga
http://phq4iiqb5.bkt.clouddn.com/posche.svga
http://phq4iiqb5.bkt.clouddn.com/kingset.svga
http://phq4iiqb5.bkt.clouddn.com/TwitterHeart.svga
http://phq4iiqb5.bkt.clouddn.com/angel.svga