把礼物动画从舞台的view中移出来 单一职责
This commit is contained in:
@@ -160,6 +160,7 @@
|
||||
E824546626F5FF6000BE8163 /* XPMineResetPayPasswordProtocol.h in Sources */ = {isa = PBXBuildFile; fileRef = E824546526F5FF5100BE8163 /* XPMineResetPayPasswordProtocol.h */; };
|
||||
E82EE0F8272FDDFA00D15DC1 /* UserPrivacyView.m in Sources */ = {isa = PBXBuildFile; fileRef = E82EE0F7272FDDFA00D15DC1 /* UserPrivacyView.m */; };
|
||||
E833ED0D274FAD1C00A2463B /* XPKickUserModel.m in Sources */ = {isa = PBXBuildFile; fileRef = E833ED0C274FAD1C00A2463B /* XPKickUserModel.m */; };
|
||||
E838D9A0275E1BF60079E0B5 /* XPRoomAnimationView.m in Sources */ = {isa = PBXBuildFile; fileRef = E838D99F275E1BF60079E0B5 /* XPRoomAnimationView.m */; };
|
||||
E83DB47A27462C4500D8CBD1 /* XPGiftBigPrizeModel.m in Sources */ = {isa = PBXBuildFile; fileRef = E83DB47927462C4500D8CBD1 /* XPGiftBigPrizeModel.m */; };
|
||||
E83DB47D2746372300D8CBD1 /* XPRoomGiftBannerView.m in Sources */ = {isa = PBXBuildFile; fileRef = E83DB47C2746372300D8CBD1 /* XPRoomGiftBannerView.m */; };
|
||||
E83DB481274649FB00D8CBD1 /* XPGiftBannerUserInfoModel.m in Sources */ = {isa = PBXBuildFile; fileRef = E83DB480274649FB00D8CBD1 /* XPGiftBannerUserInfoModel.m */; };
|
||||
@@ -608,6 +609,8 @@
|
||||
E82EE0F7272FDDFA00D15DC1 /* UserPrivacyView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = UserPrivacyView.m; sourceTree = "<group>"; };
|
||||
E833ED0B274FAD1C00A2463B /* XPKickUserModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XPKickUserModel.h; sourceTree = "<group>"; };
|
||||
E833ED0C274FAD1C00A2463B /* XPKickUserModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XPKickUserModel.m; sourceTree = "<group>"; };
|
||||
E838D99E275E1BF60079E0B5 /* XPRoomAnimationView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XPRoomAnimationView.h; sourceTree = "<group>"; };
|
||||
E838D99F275E1BF60079E0B5 /* XPRoomAnimationView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XPRoomAnimationView.m; sourceTree = "<group>"; };
|
||||
E83DB47827462C4500D8CBD1 /* XPGiftBigPrizeModel.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XPGiftBigPrizeModel.h; sourceTree = "<group>"; };
|
||||
E83DB47927462C4500D8CBD1 /* XPGiftBigPrizeModel.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = XPGiftBigPrizeModel.m; sourceTree = "<group>"; };
|
||||
E83DB47B2746372300D8CBD1 /* XPRoomGiftBannerView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = XPRoomGiftBannerView.h; sourceTree = "<group>"; };
|
||||
@@ -1706,6 +1709,22 @@
|
||||
path = Cell;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E838D99D275E1B6C0079E0B5 /* AnimationView */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E83DB47E274649B200D8CBD1 /* Model */,
|
||||
E8C214FF274B76F60079E6BF /* XPRoomAnimationHitView.h */,
|
||||
E8C21500274B76F60079E6BF /* XPRoomAnimationHitView.m */,
|
||||
E83DB47B2746372300D8CBD1 /* XPRoomGiftBannerView.h */,
|
||||
E83DB47C2746372300D8CBD1 /* XPRoomGiftBannerView.m */,
|
||||
E83DB4822746661800D8CBD1 /* XPRoomGiftBroadcastView.h */,
|
||||
E83DB4832746661800D8CBD1 /* XPRoomGiftBroadcastView.m */,
|
||||
E838D99E275E1BF60079E0B5 /* XPRoomAnimationView.h */,
|
||||
E838D99F275E1BF60079E0B5 /* XPRoomAnimationView.m */,
|
||||
);
|
||||
path = AnimationView;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
E83DB47E274649B200D8CBD1 /* Model */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
@@ -2042,6 +2061,7 @@
|
||||
E8AEAED8271413530017FCE0 /* View */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E838D99D275E1B6C0079E0B5 /* AnimationView */,
|
||||
E82325EA274E2D52003A3332 /* UserCard */,
|
||||
E8AEAED4271412EC0017FCE0 /* XPRoomViewController.h */,
|
||||
E8AEAED5271412EC0017FCE0 /* XPRoomViewController.m */,
|
||||
@@ -2086,15 +2106,8 @@
|
||||
E8AEAEE727141ACC0017FCE0 /* BaseUIContainerView */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E83DB47E274649B200D8CBD1 /* Model */,
|
||||
E8AEAEEB27141AE20017FCE0 /* XPRoomBackContainerView.h */,
|
||||
E8AEAEEC27141AE20017FCE0 /* XPRoomBackContainerView.m */,
|
||||
E8C214FF274B76F60079E6BF /* XPRoomAnimationHitView.h */,
|
||||
E8C21500274B76F60079E6BF /* XPRoomAnimationHitView.m */,
|
||||
E83DB47B2746372300D8CBD1 /* XPRoomGiftBannerView.h */,
|
||||
E83DB47C2746372300D8CBD1 /* XPRoomGiftBannerView.m */,
|
||||
E83DB4822746661800D8CBD1 /* XPRoomGiftBroadcastView.h */,
|
||||
E83DB4832746661800D8CBD1 /* XPRoomGiftBroadcastView.m */,
|
||||
);
|
||||
path = BaseUIContainerView;
|
||||
sourceTree = "<group>";
|
||||
@@ -2881,6 +2894,7 @@
|
||||
E8788934273A53D700BF1D57 /* XPSendGiftView.m in Sources */,
|
||||
E88B5CB826FB325200DA9178 /* XPMineTeenagerPwdPresenter.m in Sources */,
|
||||
E84B0E462727EF9D008818C6 /* XPRoomMessageParser.m in Sources */,
|
||||
E838D9A0275E1BF60079E0B5 /* XPRoomAnimationView.m in Sources */,
|
||||
E874B88827215D39003954B9 /* MicroStateModel.m in Sources */,
|
||||
E89D60C1271D64B9001F8895 /* RoomInfoModel.m in Sources */,
|
||||
E89DA66727006443008483C1 /* RechargeStorage.m in Sources */,
|
||||
|
17
xplan-ios/Main/Room/View/AnimationView/XPRoomAnimationView.h
Normal file
17
xplan-ios/Main/Room/View/AnimationView/XPRoomAnimationView.h
Normal file
@@ -0,0 +1,17 @@
|
||||
//
|
||||
// XPRoomAnimationView.h
|
||||
// xplan-ios
|
||||
//
|
||||
// Created by 冯硕 on 2021/12/6.
|
||||
//
|
||||
|
||||
#import <UIKit/UIKit.h>
|
||||
#import "XPRoomAnimationHitView.h"
|
||||
#import "RoomHostDelegate.h"
|
||||
NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface XPRoomAnimationView : XPRoomAnimationHitView
|
||||
- (instancetype)initWithdelegate:(id<RoomHostDelegate>)delegate;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
817
xplan-ios/Main/Room/View/AnimationView/XPRoomAnimationView.m
Normal file
817
xplan-ios/Main/Room/View/AnimationView/XPRoomAnimationView.m
Normal file
@@ -0,0 +1,817 @@
|
||||
//
|
||||
// XPRoomAnimationView.m
|
||||
// xplan-ios
|
||||
//
|
||||
// Created by 冯硕 on 2021/12/6.
|
||||
//
|
||||
|
||||
#import "XPRoomAnimationView.h"
|
||||
///Third
|
||||
#import <Masonry/Masonry.h>
|
||||
#import <SVGA.h>
|
||||
#import <NIMSDK/NIMSDK.h>
|
||||
#import <POP.h>
|
||||
///Tool
|
||||
#import "XPGiftStorage.h"
|
||||
#import "XPMacro.h"
|
||||
#import "ThemeColor+Room.h"
|
||||
#import "NetImageView.h"
|
||||
///Model
|
||||
#import "MicroQueueModel.h"
|
||||
#import "MicroStateModel.h"
|
||||
#import "UserInfoModel.h"
|
||||
#import "GiftReceiveInfoModel.h"
|
||||
#import "GiftInfoModel.h"
|
||||
#import "RoomInfoModel.h"
|
||||
#import "AttachmentModel.h"
|
||||
#import "XPGiftBigPrizeModel.h"
|
||||
#import "XPGiftBannerUserInfoModel.h"
|
||||
#import "XPRoomGiftBroadCastModel.h"
|
||||
///View
|
||||
#import "XPRoomGiftBannerView.h"
|
||||
#import "XPRoomGiftBroadcastView.h"
|
||||
|
||||
|
||||
@interface XPRoomAnimationView ()<SVGAPlayerDelegate, NIMChatManagerDelegate,NIMBroadcastManagerDelegate, XPRoomGiftBroadcastViewDelegate>
|
||||
///展示的不同层级
|
||||
///最底层的
|
||||
@property (nonatomic,strong) XPRoomAnimationHitView * lowLevelView;
|
||||
///中层的
|
||||
@property (nonatomic,strong) XPRoomAnimationHitView * middleLevelView;
|
||||
///高层的
|
||||
@property (nonatomic,strong) XPRoomAnimationHitView * highLevleView;
|
||||
///动画管理类
|
||||
@property (strong, nonatomic) SVGAParser *parser;
|
||||
///送礼物的特效
|
||||
@property (nonatomic,strong) SVGAImageView *giftEffectView;
|
||||
///代理
|
||||
@property (nonatomic,weak) id<RoomHostDelegate>delegate;
|
||||
///礼物特效的队列
|
||||
@property (nonatomic,strong) NSMutableArray<GiftReceiveInfoModel *> *giftEffectQueue;
|
||||
///复用池
|
||||
@property (strong,nonatomic)NSMutableSet * bannerDequePool;
|
||||
///可见池
|
||||
@property (strong,nonatomic)NSMutableSet * bannerVisiablePool;
|
||||
///礼物定时器 6s刷新一次
|
||||
@property (nonatomic,strong)dispatch_source_t giftEffectTimer;
|
||||
|
||||
///福袋大礼物的队列
|
||||
@property (nonatomic,strong) NSMutableArray<XPGiftBigPrizeModel *> *bigPrizeGiftQueue;
|
||||
///福袋
|
||||
@property (nonatomic,strong)dispatch_source_t luckyprizeTimer;
|
||||
|
||||
///全服广播 礼物飘屏
|
||||
@property (nonatomic,strong) NSMutableArray<XPRoomGiftBroadCastModel *> *giftBroadcastQueue;
|
||||
#pragma mark - 送礼物的动画的
|
||||
///礼物的队列
|
||||
@property (nonatomic,strong) NSMutableArray<GiftReceiveInfoModel *> *giftQueue;
|
||||
///定时器
|
||||
@property (nonatomic ,strong)dispatch_source_t giftTimer;
|
||||
///复用池 应为送礼物的动画是一个很频繁的事情 所以可以减少内存的消耗
|
||||
@property (nonatomic,strong) NSMutableSet<NetImageView *> * giftReuseArray;
|
||||
///可见池
|
||||
@property (nonatomic,strong) NSMutableSet<NetImageView *> * giftVisibleArray;
|
||||
@end
|
||||
|
||||
@implementation XPRoomAnimationView
|
||||
|
||||
- (void)dealloc {
|
||||
[NSObject cancelPreviousPerformRequestsWithTarget:self];
|
||||
}
|
||||
|
||||
- (instancetype)initWithdelegate:(id<RoomHostDelegate>)delegate {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[[NIMSDK sharedSDK].chatManager addDelegate:self];
|
||||
[[NIMSDK sharedSDK].broadcastManager addDelegate:self];
|
||||
self.delegate = delegate;
|
||||
[self initSubViews];
|
||||
[self initSubViewConstraints];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
#pragma mark - Private Method
|
||||
- (void)initSubViews {
|
||||
[self addSubview:self.lowLevelView];
|
||||
[self addSubview:self.middleLevelView];
|
||||
[self addSubview:self.highLevleView];
|
||||
}
|
||||
|
||||
- (void)initSubViewConstraints {
|
||||
[self.lowLevelView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.edges.mas_equalTo(self);
|
||||
}];
|
||||
|
||||
[self.middleLevelView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.edges.mas_equalTo(self);
|
||||
}];
|
||||
|
||||
[self.highLevleView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.edges.mas_equalTo(self);
|
||||
}];
|
||||
}
|
||||
#pragma mark - NIMChatManagerDelegate
|
||||
- (void)onRecvMessages:(NSArray<NIMMessage *> *)messages {
|
||||
for (NIMMessage * message in messages) {
|
||||
[self handleMessage:message];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - NIMBroadcastDelegate
|
||||
// 广播消息
|
||||
- (void)onReceiveBroadcastMessage:(NIMBroadcastMessage *)broadcastMessage{
|
||||
if (broadcastMessage.content) {
|
||||
NSDictionary *msgDictionary = [broadcastMessage.content toJSONObject];
|
||||
AttachmentModel *attachment = [AttachmentModel modelWithJSON:msgDictionary[@"body"]];
|
||||
if (attachment.first == CustomMessageType_Gift && attachment.second == Custom_Message_Sub_Gift_ChannelNotify){///广播 全服礼物飘屏
|
||||
[self receiveBroadcastGift:attachment];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//发送消息成功回调
|
||||
- (void)sendMessage:(NIMMessage *)message didCompleteWithError:(NSError *)error {
|
||||
[self handleMessage:message];
|
||||
}
|
||||
|
||||
- (void)handleMessage:(NIMMessage *)message {
|
||||
if (message.session.sessionType == NIMSessionTypeChatroom && message.messageType == NIMMessageTypeCustom) {
|
||||
NIMCustomObject *obj = (NIMCustomObject *)message.messageObject;
|
||||
if (obj.attachment != nil && [obj.attachment isKindOfClass:[AttachmentModel class]]) {
|
||||
AttachmentModel *attachment = (AttachmentModel *)obj.attachment;
|
||||
if (attachment.first == CustomMessageType_Gift) {
|
||||
GiftReceiveInfoModel * receiveInfo = [GiftReceiveInfoModel modelWithJSON:attachment.data];
|
||||
receiveInfo.isLuckyBagGift = attachment.second == Custom_Message_Sub_Gift_LuckySend;
|
||||
receiveInfo.isBatch = YES;
|
||||
[self receiveGiftHandleSendGiftAnimation:attachment];
|
||||
[self receiveGift:receiveInfo];
|
||||
} else if (attachment.first == CustomMessageType_AllMicroSend) { //发送全麦礼物 或者多人礼物
|
||||
GiftReceiveInfoModel * receiveInfo = [GiftReceiveInfoModel modelWithJSON:attachment.data];
|
||||
receiveInfo.isLuckyBagGift = (attachment.second == Custom_Message_Sub_AllMicroLuckySend || attachment.second == Custom_Message_Sub_AllBatchMicroLuckySend);
|
||||
receiveInfo.isBatch = (attachment.second == Custom_Message_Sub_AllBatchSend || attachment.second == Custom_Message_Sub_AllBatchMicroLuckySend);
|
||||
[self receiveGiftHandleSendGiftAnimation:attachment];
|
||||
[self receiveGift:receiveInfo];
|
||||
} else if (attachment.first == CustomMessageType_LuckyBag) {//福袋消息厅内展示
|
||||
[self receiveLuckyGiftBigPrize:attachment];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - 收到礼物展示动画
|
||||
- (void)receiveGiftHandleSendGiftAnimation:(AttachmentModel *)attachment {
|
||||
GiftReceiveInfoModel * receiveInfo = [GiftReceiveInfoModel modelWithJSON:attachment.data];
|
||||
GiftInfoModel * giftInfo = receiveInfo.gift ? receiveInfo.gift : receiveInfo.giftInfo;
|
||||
if (attachment.second == Custom_Message_Sub_AllMicroLuckySend || attachment.second == Custom_Message_Sub_AllBatchMicroLuckySend || attachment.second == Custom_Message_Sub_Gift_LuckySend) {
|
||||
NSString * giftId = [NSString stringWithFormat:@"%ld", receiveInfo.luckyGiftList.giftList.firstObject.giftId];
|
||||
giftInfo = [[XPGiftStorage shareStorage] findGiftInfo:giftId];
|
||||
}
|
||||
if (giftInfo == nil) {
|
||||
giftInfo = [[XPGiftStorage shareStorage] findGiftInfo:receiveInfo.giftId];
|
||||
}
|
||||
|
||||
///在最外面判断是否可以拿到那个礼物 后面使用就不用判断了
|
||||
receiveInfo.gift = giftInfo;
|
||||
receiveInfo.isLuckyBagGift = (attachment.second == Custom_Message_Sub_AllMicroLuckySend || attachment.second == Custom_Message_Sub_AllBatchMicroLuckySend || attachment.second == Custom_Message_Sub_Gift_LuckySend);
|
||||
[self.giftQueue addObject:receiveInfo];
|
||||
if (self.giftTimer == nil && self.giftQueue > 0) {
|
||||
[self startGiftQueueTimer];
|
||||
}
|
||||
}
|
||||
|
||||
//扫描礼物队列
|
||||
- (void)startGiftQueueTimer {
|
||||
NSTimeInterval period = 0.5; //设置时间间隔一个礼物动画的时间
|
||||
dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
|
||||
dispatch_source_set_timer(_timer, DISPATCH_TIME_NOW, period * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
|
||||
dispatch_source_set_event_handler(_timer, ^{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (self.giftQueue.count) {
|
||||
GiftReceiveInfoModel * receiveInfo = self.giftQueue.firstObject;
|
||||
[self handoutGiftDistributeAnimation:receiveInfo];
|
||||
[self.giftQueue removeObject:receiveInfo];
|
||||
}else {
|
||||
dispatch_source_cancel(_timer);
|
||||
self.giftTimer = nil;
|
||||
}
|
||||
});
|
||||
});
|
||||
dispatch_resume(_timer);
|
||||
self.giftTimer = _timer;
|
||||
}
|
||||
|
||||
///处理礼物的分发动画
|
||||
- (void)handoutGiftDistributeAnimation:(GiftReceiveInfoModel *)receiveInfo {
|
||||
GiftInfoModel * giftInfo = receiveInfo.gift;
|
||||
NSString * sendUid = receiveInfo.uid;
|
||||
CGPoint starPoint = [self getGiftAnimationPoint:sendUid isEnd:NO];
|
||||
CGPoint endPoint;
|
||||
if (receiveInfo.targetUids.count > 0) {
|
||||
if (receiveInfo.isLuckyBagGift) {
|
||||
NSString * targetUid = [NSString stringWithFormat:@"%ld", receiveInfo.luckyGiftList.user.uid];
|
||||
endPoint = [self getGiftAnimationPoint:targetUid isEnd:YES];
|
||||
dispatch_time_t timer = dispatch_time(DISPATCH_TIME_NOW, 0.5 * NSEC_PER_SEC);
|
||||
dispatch_after(timer, dispatch_get_main_queue(), ^{
|
||||
[self beginGiftAnimation:giftInfo.giftUrl startPoint:starPoint endPoint:endPoint];
|
||||
});
|
||||
} else {
|
||||
for (NSString *targetUid in receiveInfo.targetUids) {
|
||||
endPoint = [self getGiftAnimationPoint:targetUid isEnd:YES];
|
||||
dispatch_time_t timer = dispatch_time(DISPATCH_TIME_NOW, 0.5 * NSEC_PER_SEC);
|
||||
dispatch_after(timer, dispatch_get_main_queue(), ^{
|
||||
[self beginGiftAnimation:giftInfo.giftUrl startPoint:starPoint endPoint:endPoint];
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
NSString * targetUid = receiveInfo.targetUid;
|
||||
endPoint = [self getGiftAnimationPoint:targetUid isEnd:YES];
|
||||
dispatch_time_t timer = dispatch_time(DISPATCH_TIME_NOW, 0.5 * NSEC_PER_SEC);
|
||||
dispatch_after(timer, dispatch_get_main_queue(), ^{
|
||||
[self beginGiftAnimation:giftInfo.giftUrl startPoint:starPoint endPoint:endPoint];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
///起点
|
||||
- (CGPoint)getGiftAnimationPoint:(NSString *)uid isEnd:(BOOL)isEnd{
|
||||
CGPoint point = [self.delegate centerForUserAtUid:uid];
|
||||
//没有找到那个点 那个用户不再坑位上
|
||||
if (point.x <= 0 || point.y <= 0) {
|
||||
if (isEnd) {
|
||||
point = CGPointMake([UIScreen mainScreen].bounds.size.width /2 + 30, 44);
|
||||
} else {
|
||||
point = CGPointMake([UIScreen mainScreen].bounds.size.width / 2, 44);
|
||||
}
|
||||
}
|
||||
return point;
|
||||
}
|
||||
|
||||
- (void)beginGiftAnimation:(NSString *)giftUrl startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint {
|
||||
NetImageView * giftImageView = [self.giftReuseArray anyObject];
|
||||
if (giftImageView == nil) {
|
||||
giftImageView = [[NetImageView alloc]initWithFrame:CGRectMake(0, 0 , 55, 55)];
|
||||
giftImageView.center = startPoint;
|
||||
giftImageView.alpha = 1;
|
||||
giftImageView.layer.anchorPoint = CGPointMake(0.5, 0.5);
|
||||
giftImageView.imageUrl = giftUrl;
|
||||
[self.giftVisibleArray addObject:giftImageView];
|
||||
}else {
|
||||
[self.giftReuseArray removeObject:giftImageView];
|
||||
}
|
||||
giftImageView.hidden = NO;
|
||||
giftImageView.imageUrl = giftUrl;
|
||||
[self.lowLevelView addSubview:giftImageView];
|
||||
CAAnimationGroup *group = [self createGiftAnimationStartPoint:startPoint endPoint:endPoint];
|
||||
[giftImageView.layer addAnimation:group forKey:@"giftDisplayViewAnimation"];
|
||||
[self performSelector:@selector(aniationDidFinish:) withObject:giftImageView afterDelay:(3.2+0.25)];
|
||||
}
|
||||
|
||||
/// 图片运动的动画组
|
||||
/// @param startPoint 开始的点
|
||||
/// @param endPoint 结束的点
|
||||
- (CAAnimationGroup *)createGiftAnimationStartPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint{
|
||||
CGPoint centerPoint = CGPointMake(KScreenWidth / 2, KScreenHeight / 2);
|
||||
CAKeyframeAnimation *animation0 = [CAKeyframeAnimation animation];
|
||||
animation0.duration = 0.8;
|
||||
animation0.keyPath = @"transform.scale";
|
||||
animation0.values = @[@1.0,@1.5,@2.0,@1.5];
|
||||
animation0.repeatCount = 1;
|
||||
animation0.calculationMode = kCAAnimationCubic;
|
||||
animation0.removedOnCompletion = NO;
|
||||
animation0.fillMode = kCAFillModeForwards;
|
||||
|
||||
CAKeyframeAnimation *animation1 = [CAKeyframeAnimation animation];
|
||||
animation1.duration = 0.8;
|
||||
animation1.beginTime = 0.8;
|
||||
animation1.keyPath = @"transform.scale";
|
||||
animation1.values = @[@1.5,@2.0,@2.5,@3.0];
|
||||
animation1.repeatCount = 1;
|
||||
animation1.calculationMode = kCAAnimationCubic;
|
||||
animation1.removedOnCompletion = NO;
|
||||
animation1.fillMode = kCAFillModeForwards;
|
||||
|
||||
|
||||
CAKeyframeAnimation *animation2 = [CAKeyframeAnimation animation];
|
||||
animation2.duration = 0.8;
|
||||
animation2.beginTime = 0.8;
|
||||
animation2.keyPath = @"position";
|
||||
animation2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];;
|
||||
animation2.values = @[[NSValue valueWithCGPoint:startPoint],[NSValue valueWithCGPoint:CGPointMake(centerPoint.x ,centerPoint.y)]];
|
||||
animation2.repeatCount = 1;
|
||||
animation2.removedOnCompletion = NO;
|
||||
animation2.fillMode = kCAFillModeForwards;
|
||||
|
||||
CAKeyframeAnimation *animation3 = [CAKeyframeAnimation animation];
|
||||
animation3.duration = 0.8;
|
||||
animation3.beginTime = 2.6;//0.8+0.8+1
|
||||
animation3.keyPath = @"transform.scale";
|
||||
animation3.values = @[@3,@2.5,@2,@1.5,@1];
|
||||
animation3.repeatCount = 1;
|
||||
|
||||
CAKeyframeAnimation *animation4 = [CAKeyframeAnimation animation];
|
||||
animation4.duration = 0.8;
|
||||
animation4.beginTime = 2.6;
|
||||
animation4.keyPath = @"position";
|
||||
animation4.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
|
||||
animation4.values = @[[NSValue valueWithCGPoint:CGPointMake(centerPoint.x ,centerPoint.y)],[NSValue valueWithCGPoint:endPoint]];
|
||||
animation4.repeatCount = 1;
|
||||
|
||||
CAAnimationGroup *group = [CAAnimationGroup animation];
|
||||
group.duration = 3.2;
|
||||
group.animations = @[animation0,animation1,animation2, animation3,animation4];
|
||||
group.repeatCount = 1;
|
||||
group.removedOnCompletion = NO;
|
||||
group.fillMode = kCAFillModeForwards;
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
- (void)aniationDidFinish:(NetImageView *)giftImageView{
|
||||
[giftImageView removeFromSuperview];
|
||||
giftImageView.image = nil;
|
||||
giftImageView.hidden = YES;
|
||||
[self.giftVisibleArray removeObject:giftImageView];
|
||||
[self.giftReuseArray addObject:giftImageView];
|
||||
}
|
||||
|
||||
#pragma mark - 全服礼物 飘屏
|
||||
- (void)receiveBroadcastGift:(AttachmentModel *)attachment {
|
||||
XPRoomGiftBroadCastModel *giftNotifyInfo = [XPRoomGiftBroadCastModel modelWithJSON:attachment.data];
|
||||
if (self.giftBroadcastQueue.count == 0) {
|
||||
[self createGiftBroadcastViewAnimation:giftNotifyInfo];
|
||||
}
|
||||
[self.giftBroadcastQueue addObject:giftNotifyInfo];
|
||||
}
|
||||
|
||||
- (void)createGiftBroadcastViewAnimation:(XPRoomGiftBroadCastModel *)giftModel {
|
||||
XPRoomGiftBroadcastView * view = [[XPRoomGiftBroadcastView alloc] init];
|
||||
view.delegate = self;
|
||||
view.frame = CGRectMake(KScreenWidth, 35 + statusbarHeight, KScreenWidth, 150);
|
||||
view.broadcastModel = giftModel;
|
||||
[self.highLevleView addSubview:view];
|
||||
[self beginGiftBraodcastViewAnimation:view notifyStaySecond:giftModel.notifyStaySecond];
|
||||
}
|
||||
|
||||
- (void)beginGiftBraodcastViewAnimation:(XPRoomGiftBroadcastView *)view notifyStaySecond:(int)notifyStaySecond{
|
||||
CGFloat startTime = notifyStaySecond > 0 ? notifyStaySecond : 3.0;
|
||||
POPSpringAnimation *springAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter];
|
||||
springAnimation.springSpeed = 12;
|
||||
springAnimation.springBounciness = 10.f;
|
||||
springAnimation.fromValue = [NSValue valueWithCGPoint:view.center];
|
||||
springAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(0 + view.frame.size.width / 2, view.center.y)];
|
||||
[springAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
|
||||
if (finished) {
|
||||
[self removeGiftBroadcastOutAnimation:view stayTime:startTime];
|
||||
}
|
||||
}];
|
||||
[view pop_addAnimation:springAnimation forKey:@"spingOutAnimation"];
|
||||
}
|
||||
|
||||
- (void)removeGiftBroadcastOutAnimation:(XPRoomGiftBroadcastView *)view stayTime:(CGFloat)stayTime{
|
||||
POPBasicAnimation *moveAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPViewCenter];
|
||||
moveAnimation.fromValue = [NSValue valueWithCGPoint:view.center];
|
||||
moveAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(-KScreenWidth/2, view.center.y)];
|
||||
moveAnimation.beginTime = CACurrentMediaTime() + stayTime;
|
||||
moveAnimation.duration = 0.5;
|
||||
moveAnimation.repeatCount = 1;
|
||||
moveAnimation.removedOnCompletion = YES;
|
||||
@kWeakify(self);
|
||||
[moveAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
|
||||
@kStrongify(self);
|
||||
if (finished) {
|
||||
[view removeFromSuperview];
|
||||
[self.giftBroadcastQueue removeObjectAtIndex:0];
|
||||
if (self.giftBroadcastQueue.count > 0) {
|
||||
[self createGiftBroadcastViewAnimation:self.giftBroadcastQueue.firstObject];
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
||||
[view pop_addAnimation:moveAnimation forKey:@"moveOutAnimation"];
|
||||
}
|
||||
|
||||
#pragma mark - XPRoomGiftBroadcastViewDelegate
|
||||
- (void)xPRoomGiftBroadcastView:(XPRoomGiftBroadcastView *)view enterRoom:(NSString *)roomUid {
|
||||
//TODO: 退出当前房间 换个房间
|
||||
}
|
||||
|
||||
- (void)xPRoomGiftBroadcastView:(XPRoomGiftBroadcastView *)view didClickClose:(XPRoomGiftBroadCastModel *)broadcastModel {
|
||||
[view removeFromSuperview];
|
||||
[view pop_removeAllAnimations];
|
||||
if ([self.giftBroadcastQueue containsObject:broadcastModel]) {
|
||||
[self.giftBroadcastQueue removeObject:broadcastModel];
|
||||
}
|
||||
if (self.giftBroadcastQueue.count > 0) {
|
||||
[self createGiftBroadcastViewAnimation:self.giftBroadcastQueue.firstObject];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - 福袋中 四级奖品
|
||||
- (void)receiveLuckyGiftBigPrize:(AttachmentModel *)attachment {
|
||||
if (attachment.second == Custom_Message_Sub_Room_Gift_LuckBag || attachment.second == Custom_Message_Sub_Room_Gift_LuckBag_Server) {
|
||||
XPGiftBigPrizeModel * prizeModel = [[XPGiftBigPrizeModel alloc] init];
|
||||
prizeModel.giftName = attachment.data[@"giftName"];
|
||||
prizeModel.luckyBagName = attachment.data[@"luckyBagName"];
|
||||
prizeModel.nick = attachment.data[@"nick"];
|
||||
[self.bigPrizeGiftQueue addObject:prizeModel];
|
||||
if (self.luckyprizeTimer == nil) {
|
||||
[self startHandleBigPrizeGiftTimer];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)startHandleBigPrizeGiftTimer {
|
||||
NSTimeInterval period = 1.0; //设置时间间隔
|
||||
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
|
||||
dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
|
||||
dispatch_source_set_timer(_timer, dispatch_walltime(NULL, 0), period * NSEC_PER_SEC, 0); //每秒执行
|
||||
@kWeakify(self);
|
||||
dispatch_source_set_event_handler(_timer, ^{
|
||||
@kStrongify(self)
|
||||
if (self.bigPrizeGiftQueue.count > 0) {
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
XPGiftBigPrizeModel * prizeModel = [self.bigPrizeGiftQueue firstObject];
|
||||
[self createBigPrizeAnimation:prizeModel];
|
||||
[self.bigPrizeGiftQueue removeObject:prizeModel];
|
||||
});
|
||||
}else {
|
||||
dispatch_source_cancel(_timer);
|
||||
self.luckyprizeTimer = nil;
|
||||
}
|
||||
});
|
||||
dispatch_resume(_timer);
|
||||
self.luckyprizeTimer = _timer;
|
||||
}
|
||||
|
||||
- (void)createBigPrizeAnimation:(XPGiftBigPrizeModel *)prizeModel {
|
||||
NSAttributedString *text = [self createBigPrizeAttribute:prizeModel];
|
||||
UIImageView *luckyBgView = [[UIImageView alloc] initWithFrame:CGRectMake(KScreenWidth, kNavigationHeight + 15, KScreenWidth, 45)];
|
||||
luckyBgView.contentMode = UIViewContentModeScaleAspectFill;
|
||||
luckyBgView.image= [UIImage imageNamed:@"room_lucky_gift_big_prize_bg"];
|
||||
UILabel *contentLabel = [[UILabel alloc] initWithFrame:CGRectMake(90, 0, KScreenWidth - 160, 45)];
|
||||
contentLabel.attributedText = text;
|
||||
contentLabel.textAlignment = NSTextAlignmentCenter;
|
||||
contentLabel.numberOfLines = 2;
|
||||
[luckyBgView addSubview:contentLabel];
|
||||
[self.lowLevelView addSubview:luckyBgView];
|
||||
[UIView animateWithDuration:0.5 animations:^{
|
||||
luckyBgView.frame = CGRectMake(0, kNavigationHeight + 15, KScreenWidth, 45);
|
||||
} completion:^(BOOL finished) {
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
[UIView animateWithDuration:0.5 animations:^{
|
||||
luckyBgView.hidden = YES;
|
||||
} completion:^(BOOL finished) {
|
||||
[luckyBgView removeFromSuperview];
|
||||
}];
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
- (NSAttributedString *)createBigPrizeAttribute:(XPGiftBigPrizeModel *)prizModel {
|
||||
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] init];
|
||||
[attributedString appendAttributedString:
|
||||
[self createTextAttribute:@"哇偶 ! "
|
||||
color:[ThemeColor messageViewTipColor] font:12]];
|
||||
[attributedString appendAttributedString:
|
||||
[self createTextAttribute:prizModel.nick
|
||||
color:[ThemeColor messageNickColor] font:12]];
|
||||
|
||||
[attributedString appendAttributedString:
|
||||
[self createTextAttribute:@"通过"
|
||||
color:[ThemeColor messageViewTipColor] font:12]];
|
||||
|
||||
[attributedString appendAttributedString:
|
||||
[self createTextAttribute:prizModel.luckyBagName
|
||||
color:[ThemeColor messageNickColor] font:12]];
|
||||
|
||||
[attributedString appendAttributedString:
|
||||
[self createTextAttribute:@"开出了"
|
||||
color:[ThemeColor messageNickColor] font:12]];
|
||||
|
||||
[attributedString appendAttributedString:
|
||||
[self createTextAttribute:prizModel.giftName color:[ThemeColor messageNickColor] font:12]];
|
||||
return attributedString;
|
||||
}
|
||||
|
||||
/// 生成一个富文本
|
||||
/// @param text 富文本的文字
|
||||
/// @param color 文字的颜色
|
||||
/// @param font 文字的大小
|
||||
- (NSMutableAttributedString *)createTextAttribute:(NSString *)text color:(UIColor *)color font:(CGFloat)font {
|
||||
if (text == nil || text.length <= 0) {
|
||||
text = @"";
|
||||
}
|
||||
NSDictionary * dic = @{NSFontAttributeName:[UIFont systemFontOfSize:12], NSForegroundColorAttributeName:color};
|
||||
NSMutableAttributedString *attribute = [[NSMutableAttributedString alloc] initWithString:text attributes:dic];
|
||||
return attribute;
|
||||
}
|
||||
|
||||
#pragma mark - 普通礼物
|
||||
///收到了礼物
|
||||
- (void)receiveGift:(GiftReceiveInfoModel *)receiveInfo {
|
||||
///CPU警告的时候 需要停止接收动画
|
||||
|
||||
RoomInfoModel * roomInfor = [self.delegate getRoomInfo];
|
||||
if (receiveInfo.isLuckyBagGift) {
|
||||
//如果是福袋礼物的话 就不用看他的价值了 只要有SVGA的话 就播放
|
||||
if (receiveInfo.displayGift.count > 0) {
|
||||
[receiveInfo.displayGift enumerateObjectsUsingBlock:^(GiftInfoModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
if (obj.hasVggPic && roomInfor.hasAnimationEffect) {
|
||||
GiftReceiveInfoModel * model = [[GiftReceiveInfoModel alloc] init];
|
||||
model.vggUrl = obj.vggUrl;
|
||||
[self.giftEffectQueue addObject:model];
|
||||
}
|
||||
}];
|
||||
}
|
||||
} else {
|
||||
GiftInfoModel *giftInfo = receiveInfo.gift == nil ? receiveInfo.gift : receiveInfo.giftInfo;
|
||||
if (!giftInfo) {
|
||||
giftInfo = [[XPGiftStorage shareStorage] findGiftInfo: receiveInfo.giftId];
|
||||
}
|
||||
///重新赋值一下 用的时候不用在查找了 真的没有的话 那就没有那个礼物了
|
||||
if (giftInfo) {
|
||||
receiveInfo.gift = giftInfo;
|
||||
}
|
||||
if (receiveInfo.targetUsers.count > 0 && receiveInfo.targetUids.count <= 0) {
|
||||
receiveInfo.targetUids = [receiveInfo.targetUsers valueForKeyPath:@"uid"];
|
||||
}
|
||||
|
||||
NSInteger giftTotal = 0;
|
||||
if (receiveInfo.targetUids.count > 0) {
|
||||
giftTotal = receiveInfo.giftNum * giftInfo.goldPrice * receiveInfo.targetUids.count;
|
||||
} else {
|
||||
giftTotal = receiveInfo.giftNum * giftInfo.goldPrice;
|
||||
}
|
||||
|
||||
///房间横幅
|
||||
if (giftTotal >= 520) {
|
||||
///房间横幅和 房间特效的关闭没有关系
|
||||
[self.giftEffectQueue addObject:receiveInfo];
|
||||
} else {
|
||||
///SVGA动画
|
||||
if (giftInfo.hasVggPic && roomInfor.hasAnimationEffect) {
|
||||
receiveInfo.vggUrl = giftInfo.vggUrl;
|
||||
[self.giftEffectQueue addObject:receiveInfo];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (self.giftEffectTimer == nil && self.giftEffectQueue.count > 0) {
|
||||
[self startHandleGiftEffectTimer];
|
||||
}
|
||||
}
|
||||
|
||||
///开启普通礼物特效定时器
|
||||
- (void)startHandleGiftEffectTimer {
|
||||
NSTimeInterval period = 6.0; //设置时间间隔 6秒是 1、单纯的svga 2.有横幅有svga 3、只有横幅
|
||||
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
|
||||
dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
|
||||
dispatch_source_set_timer(_timer, dispatch_walltime(NULL, 0), period * NSEC_PER_SEC, 0); //每秒执行
|
||||
@kWeakify(self);
|
||||
dispatch_source_set_event_handler(_timer, ^{
|
||||
@kStrongify(self)
|
||||
if (self.giftEffectQueue.count > 0) {
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
GiftReceiveInfoModel * receiveModel = [self.giftEffectQueue firstObject];
|
||||
[self createGiftBannerViewAnimation:receiveModel];
|
||||
[self.giftEffectQueue removeObject:receiveModel];
|
||||
});
|
||||
}else {
|
||||
dispatch_source_cancel(_timer);
|
||||
self.giftEffectTimer = nil;
|
||||
}
|
||||
});
|
||||
dispatch_resume(_timer);
|
||||
self.giftEffectTimer = _timer;
|
||||
}
|
||||
|
||||
- (void)createGiftBannerViewAnimation:(GiftReceiveInfoModel *)receiveInfo {
|
||||
GiftInfoModel * giftInfo = receiveInfo.gift;
|
||||
NSInteger giftTotal = 0;
|
||||
if (receiveInfo.targetUids.count > 0) {
|
||||
giftTotal = receiveInfo.giftNum * giftInfo.goldPrice * receiveInfo.targetUids.count;
|
||||
} else {
|
||||
giftTotal = receiveInfo.giftNum * giftInfo.goldPrice;
|
||||
}
|
||||
if (giftTotal >= 520) {
|
||||
__block XPRoomGiftBannerView *view = [self.bannerDequePool anyObject];
|
||||
if (view == nil) {
|
||||
view = [[XPRoomGiftBannerView alloc] init];
|
||||
[self.bannerVisiablePool addObject:view];
|
||||
}else{
|
||||
[self.bannerDequePool removeObject:view];
|
||||
}
|
||||
[self removeGiftBannerView:view];
|
||||
[view configGiftBanner:receiveInfo users:[self makeBannerUsers]];
|
||||
view.frame = CGRectMake(KScreenWidth, 100, KScreenWidth, 153);
|
||||
[self.lowLevelView addSubview:view];
|
||||
POPSpringAnimation *springAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter];
|
||||
springAnimation.springSpeed = 12;
|
||||
springAnimation.springBounciness = 10.f;
|
||||
springAnimation.fromValue = [NSValue valueWithCGPoint:view.center];
|
||||
springAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(view.frame.size.width / 2, view.center.y)];
|
||||
@kWeakify(self);
|
||||
[springAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
|
||||
@kStrongify(self);
|
||||
if (finished) {
|
||||
[self removeAnimation:view];
|
||||
}
|
||||
}];
|
||||
|
||||
[springAnimation setAnimationDidStartBlock:^(POPAnimation *anim) {
|
||||
@kStrongify(self);
|
||||
if (giftInfo.hasVggPic && [self.delegate getRoomInfo].hasAnimationEffect) {
|
||||
[self playGiftEffect:giftInfo.vggUrl];
|
||||
}
|
||||
}];
|
||||
|
||||
[view pop_addAnimation:springAnimation forKey:@"spingOutAnimation"];
|
||||
} else {
|
||||
if (receiveInfo.vggUrl.length > 0) {///如果有特效的话就播放特效
|
||||
[self playGiftEffect:receiveInfo.vggUrl];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//移除特效动画
|
||||
- (void)removeAnimation:(XPRoomGiftBannerView *)view{
|
||||
POPBasicAnimation *moveAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPViewCenter];
|
||||
moveAnimation.fromValue = [NSValue valueWithCGPoint:view.center];
|
||||
moveAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(view.center.x - KScreenWidth, view.center.y)];
|
||||
moveAnimation.beginTime = CACurrentMediaTime() +5;
|
||||
moveAnimation.duration = 0.5;
|
||||
moveAnimation.repeatCount = 1;
|
||||
moveAnimation.removedOnCompletion = YES;
|
||||
[view pop_addAnimation:moveAnimation forKey:@"moveOutAnimation"];
|
||||
}
|
||||
|
||||
- (NSArray<XPGiftBannerUserInfoModel *> *)makeBannerUsers {
|
||||
NSArray<MicroQueueModel *> * microArray = [self.delegate getMicroQueue].allValues;
|
||||
NSMutableArray * array = [NSMutableArray array];
|
||||
[microArray enumerateObjectsUsingBlock:^(MicroQueueModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
XPGiftBannerUserInfoModel * bannserUser = [[XPGiftBannerUserInfoModel alloc] init];
|
||||
bannserUser.position = obj.microState.position;
|
||||
bannserUser.uid = obj.userInfo.uid;
|
||||
[array addObject:bannserUser];
|
||||
}];
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
///播放礼物特效 SVGA的
|
||||
- (void)playGiftEffect:(NSString *)vggUrl {
|
||||
self.giftEffectView.hidden = NO;
|
||||
if (self.giftEffectView.superview == nil) {
|
||||
[self.middleLevelView addSubview:self.giftEffectView];
|
||||
[self.giftEffectView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.center.mas_equalTo(self.lowLevelView);
|
||||
make.width.mas_equalTo(KScreenWidth);
|
||||
make.height.mas_equalTo(KScreenHeight);
|
||||
}];
|
||||
}
|
||||
[self.parser parseWithURL:[NSURL URLWithString:vggUrl] completionBlock:^(SVGAVideoEntity * _Nullable videoItem) {
|
||||
if (videoItem != nil) {
|
||||
CGFloat width = videoItem.videoSize.width;
|
||||
CGFloat height = videoItem.videoSize.height;
|
||||
if (width > height) {
|
||||
self.giftEffectView.contentMode = UIViewContentModeScaleAspectFit;
|
||||
} else {//高大于宽
|
||||
CGFloat resizeH = KScreenWidth * height / width;//按照屏幕的宽度去缩放,获得高度
|
||||
if (resizeH > KScreenHeight) {//如果大于屏幕高度,填充
|
||||
self.giftEffectView.contentMode = UIViewContentModeScaleAspectFill;
|
||||
} else {//小于屏幕高度,
|
||||
self.giftEffectView.contentMode = UIViewContentModeScaleAspectFit;
|
||||
}
|
||||
}
|
||||
self.giftEffectView.alpha = 1;
|
||||
self.giftEffectView.loops = 1;
|
||||
self.giftEffectView.clearsAfterStop = YES;
|
||||
self.giftEffectView.videoItem = videoItem;
|
||||
[self.giftEffectView startAnimation];
|
||||
}
|
||||
} failureBlock:^(NSError * _Nullable error) {
|
||||
|
||||
}];
|
||||
}
|
||||
|
||||
///移除横幅的veiw 添加到复用池中
|
||||
- (void)removeGiftBannerView:(XPRoomGiftBannerView *)view {
|
||||
[view removeFromSuperview];
|
||||
[view resetData];
|
||||
[self.bannerVisiablePool removeObject:view];
|
||||
[self.bannerDequePool addObject:view];
|
||||
///svga的处理
|
||||
[self.giftEffectView stopAnimation];
|
||||
self.giftEffectView.hidden = YES;
|
||||
}
|
||||
#pragma mark -
|
||||
- (void)svgaPlayerDidFinishedAnimation:(SVGAPlayer *)player {
|
||||
if (player == self.giftEffectView) {
|
||||
self.giftEffectView.hidden = YES;
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - Getters And Setters
|
||||
- (SVGAImageView *)giftEffectView {
|
||||
if (!_giftEffectView) {
|
||||
_giftEffectView = [[SVGAImageView alloc]init];
|
||||
_giftEffectView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
|
||||
_giftEffectView.userInteractionEnabled = NO;
|
||||
_giftEffectView.delegate = self;
|
||||
_giftEffectView.hidden = YES;
|
||||
}
|
||||
return _giftEffectView;
|
||||
}
|
||||
|
||||
- (SVGAParser *)parser {
|
||||
if (!_parser) {
|
||||
_parser = [[SVGAParser alloc]init];
|
||||
}
|
||||
return _parser;
|
||||
}
|
||||
|
||||
- (NSMutableArray<GiftReceiveInfoModel *> *)giftEffectQueue {
|
||||
if (!_giftEffectQueue) {
|
||||
_giftEffectQueue = [NSMutableArray array];
|
||||
}
|
||||
return _giftEffectQueue;
|
||||
}
|
||||
|
||||
- (NSMutableArray<XPGiftBigPrizeModel *> *)bigPrizeGiftQueue {
|
||||
if (!_bigPrizeGiftQueue) {
|
||||
_bigPrizeGiftQueue = [NSMutableArray array];
|
||||
}
|
||||
return _bigPrizeGiftQueue;
|
||||
}
|
||||
|
||||
- (NSMutableArray<XPRoomGiftBroadCastModel *> *)giftBroadcastQueue {
|
||||
if (!_giftBroadcastQueue) {
|
||||
_giftBroadcastQueue = [NSMutableArray array];
|
||||
}
|
||||
return _giftBroadcastQueue;
|
||||
}
|
||||
|
||||
- (NSMutableSet *)bannerDequePool {
|
||||
if (!_bannerDequePool) {
|
||||
_bannerDequePool = [NSMutableSet set];
|
||||
}
|
||||
return _bannerDequePool;
|
||||
}
|
||||
- (NSMutableSet *)bannerVisiablePool {
|
||||
if (!_bannerVisiablePool) {
|
||||
_bannerVisiablePool = [NSMutableSet set];
|
||||
}
|
||||
return _bannerVisiablePool;
|
||||
}
|
||||
|
||||
- (XPRoomAnimationHitView *)lowLevelView {
|
||||
if (!_lowLevelView) {
|
||||
_lowLevelView = [[XPRoomAnimationHitView alloc] init];
|
||||
_lowLevelView.backgroundColor = [UIColor clearColor];
|
||||
_lowLevelView.userInteractionEnabled = YES;
|
||||
}
|
||||
return _lowLevelView;
|
||||
}
|
||||
|
||||
- (XPRoomAnimationHitView *)middleLevelView {
|
||||
if (!_middleLevelView) {
|
||||
_middleLevelView = [[XPRoomAnimationHitView alloc] init];
|
||||
_middleLevelView.backgroundColor = [UIColor clearColor];
|
||||
_middleLevelView.userInteractionEnabled = YES;
|
||||
}
|
||||
return _middleLevelView;
|
||||
}
|
||||
|
||||
- (XPRoomAnimationHitView *)highLevleView {
|
||||
if (!_highLevleView) {
|
||||
_highLevleView = [[XPRoomAnimationHitView alloc] init];
|
||||
_highLevleView.backgroundColor = [UIColor clearColor];
|
||||
_highLevleView.userInteractionEnabled = YES;
|
||||
}
|
||||
return _highLevleView;
|
||||
}
|
||||
|
||||
- (NSMutableArray<GiftReceiveInfoModel *> *)giftQueue {
|
||||
if (!_giftQueue) {
|
||||
_giftQueue = [NSMutableArray array];
|
||||
}
|
||||
return _giftQueue;
|
||||
}
|
||||
|
||||
- (NSMutableSet<NetImageView *> *)giftReuseArray {
|
||||
if (!_giftReuseArray) {
|
||||
_giftReuseArray = [NSMutableSet set];
|
||||
}
|
||||
return _giftReuseArray;
|
||||
}
|
||||
|
||||
- (NSMutableSet<NetImageView *> *)giftVisibleArray {
|
||||
if (!_giftVisibleArray) {
|
||||
_giftVisibleArray = [NSMutableSet set];
|
||||
}
|
||||
return _giftVisibleArray;
|
||||
}
|
||||
|
||||
@end
|
@@ -11,8 +11,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
@interface XPRoomBackContainerView : UIView
|
||||
- (instancetype)initWithdelegate:(id<RoomHostDelegate>)delegate;
|
||||
|
||||
- (void)superViewDidLayoutViews;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
@@ -8,61 +8,17 @@
|
||||
#import "XPRoomBackContainerView.h"
|
||||
///Third
|
||||
#import <Masonry/Masonry.h>
|
||||
#import <SVGA.h>
|
||||
#import <NIMSDK/NIMSDK.h>
|
||||
#import <POP.h>
|
||||
///Tool
|
||||
#import "XPGiftStorage.h"
|
||||
#import "XPMacro.h"
|
||||
#import "ThemeColor+Room.h"
|
||||
///Model
|
||||
#import "MicroQueueModel.h"
|
||||
#import "MicroStateModel.h"
|
||||
#import "UserInfoModel.h"
|
||||
#import "GiftReceiveInfoModel.h"
|
||||
#import "GiftInfoModel.h"
|
||||
#import "RoomInfoModel.h"
|
||||
#import "AttachmentModel.h"
|
||||
#import "XPGiftBigPrizeModel.h"
|
||||
#import "XPGiftBannerUserInfoModel.h"
|
||||
#import "XPRoomGiftBroadCastModel.h"
|
||||
///View
|
||||
#import "XPRoomGiftBannerView.h"
|
||||
#import "XPRoomGiftBroadcastView.h"
|
||||
#import "XPRoomAnimationHitView.h"
|
||||
|
||||
@interface XPRoomBackContainerView ()<SVGAPlayerDelegate, NIMChatManagerDelegate,NIMBroadcastManagerDelegate, XPRoomGiftBroadcastViewDelegate>
|
||||
///展示的不同层级
|
||||
///最底层的
|
||||
@property (nonatomic,strong) XPRoomAnimationHitView * lowLevelView;
|
||||
///中层的
|
||||
@property (nonatomic,strong) XPRoomAnimationHitView * middleLevelView;
|
||||
///高层的
|
||||
@property (nonatomic,strong) XPRoomAnimationHitView * highLevleView;
|
||||
///动画管理类
|
||||
@property (strong, nonatomic) SVGAParser *parser;
|
||||
///送礼物的特效
|
||||
@property (nonatomic,strong) SVGAImageView *giftEffectView;
|
||||
///
|
||||
|
||||
|
||||
@interface XPRoomBackContainerView ()
|
||||
///背景图片
|
||||
@property (nonatomic,strong) UIImageView *backImageView;
|
||||
///
|
||||
///host 代理
|
||||
@property (nonatomic,weak) id<RoomHostDelegate>delegate;
|
||||
///礼物特效的队列
|
||||
@property (nonatomic,strong) NSMutableArray<GiftReceiveInfoModel *> *giftEffectQueue;
|
||||
///复用池
|
||||
@property (strong,nonatomic)NSMutableSet * bannerDequePool;
|
||||
///可见池
|
||||
@property (strong,nonatomic)NSMutableSet * bannerVisiablePool;
|
||||
///礼物定时器 6s刷新一次
|
||||
@property (nonatomic,strong)dispatch_source_t giftEffectTimer;
|
||||
|
||||
///福袋大礼物的队列
|
||||
@property (nonatomic,strong) NSMutableArray<XPGiftBigPrizeModel *> *bigPrizeGiftQueue;
|
||||
///福袋
|
||||
@property (nonatomic,strong)dispatch_source_t luckyprizeTimer;
|
||||
|
||||
///全服广播 礼物飘屏
|
||||
@property (nonatomic,strong) NSMutableArray<XPRoomGiftBroadCastModel *> *giftBroadcastQueue;;
|
||||
@end
|
||||
|
||||
@implementation XPRoomBackContainerView
|
||||
@@ -70,8 +26,6 @@
|
||||
- (instancetype)initWithdelegate:(id<RoomHostDelegate>)delegate {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
[[NIMSDK sharedSDK].chatManager addDelegate:self];
|
||||
[[NIMSDK sharedSDK].broadcastManager addDelegate:self];
|
||||
self.delegate = delegate;
|
||||
[self initSubViews];
|
||||
[self initSubViewConstraints];
|
||||
@@ -79,33 +33,9 @@
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)superViewDidLayoutViews {
|
||||
///需要那一层的就加到那一层上面
|
||||
[self.superview addSubview:self.lowLevelView];
|
||||
[self.superview addSubview:self.middleLevelView];
|
||||
[self.superview addSubview:self.highLevleView];
|
||||
|
||||
[self.superview bringSubviewToFront:self.highLevleView];
|
||||
[self.superview insertSubview:self.middleLevelView belowSubview:self.highLevleView];
|
||||
[self.superview insertSubview:self.lowLevelView belowSubview:self.middleLevelView];
|
||||
|
||||
[self.lowLevelView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.edges.mas_equalTo(self.superview);
|
||||
}];
|
||||
|
||||
[self.middleLevelView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.edges.mas_equalTo(self.superview);
|
||||
}];
|
||||
|
||||
[self.highLevleView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.edges.mas_equalTo(self.superview);
|
||||
}];
|
||||
}
|
||||
|
||||
#pragma mark - Private Method
|
||||
- (void)initSubViews {
|
||||
[self addSubview:self.backImageView];
|
||||
|
||||
}
|
||||
|
||||
- (void)initSubViewConstraints {
|
||||
@@ -113,430 +43,6 @@
|
||||
make.edges.mas_equalTo(self);
|
||||
}];
|
||||
}
|
||||
#pragma mark - NIMChatManagerDelegate
|
||||
- (void)onRecvMessages:(NSArray<NIMMessage *> *)messages {
|
||||
for (NIMMessage * message in messages) {
|
||||
[self handleMessage:message];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - NIMBroadcastDelegate
|
||||
// 广播消息
|
||||
- (void)onReceiveBroadcastMessage:(NIMBroadcastMessage *)broadcastMessage{
|
||||
if (broadcastMessage.content) {
|
||||
NSDictionary *msgDictionary = [broadcastMessage.content toJSONObject];
|
||||
AttachmentModel *attachment = [AttachmentModel modelWithJSON:msgDictionary[@"body"]];
|
||||
if (attachment.first == CustomMessageType_Gift && attachment.second == Custom_Message_Sub_Gift_ChannelNotify){///广播 全服礼物飘屏
|
||||
[self receiveBroadcastGift:attachment];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//发送消息成功回调
|
||||
- (void)sendMessage:(NIMMessage *)message didCompleteWithError:(NSError *)error {
|
||||
[self handleMessage:message];
|
||||
}
|
||||
|
||||
- (void)handleMessage:(NIMMessage *)message {
|
||||
if (message.session.sessionType == NIMSessionTypeChatroom && message.messageType == NIMMessageTypeCustom) {
|
||||
NIMCustomObject *obj = (NIMCustomObject *)message.messageObject;
|
||||
if (obj.attachment != nil && [obj.attachment isKindOfClass:[AttachmentModel class]]) {
|
||||
AttachmentModel *attachment = (AttachmentModel *)obj.attachment;
|
||||
if (attachment.first == CustomMessageType_Gift) {
|
||||
GiftReceiveInfoModel * receiveInfo = [GiftReceiveInfoModel modelWithJSON:attachment.data];
|
||||
receiveInfo.isLuckyBagGift = attachment.second == Custom_Message_Sub_Gift_LuckySend;
|
||||
receiveInfo.isBatch = YES;
|
||||
[self receiveGift:receiveInfo];
|
||||
} else if (attachment.first == CustomMessageType_AllMicroSend) { //发送全麦礼物 或者多人礼物
|
||||
GiftReceiveInfoModel * receiveInfo = [GiftReceiveInfoModel modelWithJSON:attachment.data];
|
||||
receiveInfo.isLuckyBagGift = (attachment.second == Custom_Message_Sub_AllMicroLuckySend || attachment.second == Custom_Message_Sub_AllBatchMicroLuckySend);
|
||||
receiveInfo.isBatch = (attachment.second == Custom_Message_Sub_AllBatchSend || attachment.second == Custom_Message_Sub_AllBatchMicroLuckySend);
|
||||
[self receiveGift:receiveInfo];
|
||||
} else if (attachment.first == CustomMessageType_LuckyBag) {//福袋消息厅内展示
|
||||
[self receiveLuckyGiftBigPrize:attachment];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - 全服礼物 飘屏
|
||||
- (void)receiveBroadcastGift:(AttachmentModel *)attachment {
|
||||
XPRoomGiftBroadCastModel *giftNotifyInfo = [XPRoomGiftBroadCastModel modelWithJSON:attachment.data];
|
||||
if (self.giftBroadcastQueue.count == 0) {
|
||||
[self createGiftBroadcastViewAnimation:giftNotifyInfo];
|
||||
}
|
||||
[self.giftBroadcastQueue addObject:giftNotifyInfo];
|
||||
}
|
||||
|
||||
- (void)createGiftBroadcastViewAnimation:(XPRoomGiftBroadCastModel *)giftModel {
|
||||
XPRoomGiftBroadcastView * view = [[XPRoomGiftBroadcastView alloc] init];
|
||||
view.delegate = self;
|
||||
view.frame = CGRectMake(KScreenWidth, 35 + statusbarHeight, KScreenWidth, 150);
|
||||
view.broadcastModel = giftModel;
|
||||
[self.highLevleView addSubview:view];
|
||||
[self beginGiftBraodcastViewAnimation:view notifyStaySecond:giftModel.notifyStaySecond];
|
||||
}
|
||||
|
||||
- (void)beginGiftBraodcastViewAnimation:(XPRoomGiftBroadcastView *)view notifyStaySecond:(int)notifyStaySecond{
|
||||
CGFloat startTime = notifyStaySecond > 0 ? notifyStaySecond : 3.0;
|
||||
POPSpringAnimation *springAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter];
|
||||
springAnimation.springSpeed = 12;
|
||||
springAnimation.springBounciness = 10.f;
|
||||
springAnimation.fromValue = [NSValue valueWithCGPoint:view.center];
|
||||
springAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(0 + view.frame.size.width / 2, view.center.y)];
|
||||
[springAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
|
||||
if (finished) {
|
||||
[self removeGiftBroadcastOutAnimation:view stayTime:startTime];
|
||||
}
|
||||
}];
|
||||
[view pop_addAnimation:springAnimation forKey:@"spingOutAnimation"];
|
||||
}
|
||||
|
||||
- (void)removeGiftBroadcastOutAnimation:(XPRoomGiftBroadcastView *)view stayTime:(CGFloat)stayTime{
|
||||
POPBasicAnimation *moveAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPViewCenter];
|
||||
moveAnimation.fromValue = [NSValue valueWithCGPoint:view.center];
|
||||
moveAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(-KScreenWidth/2, view.center.y)];
|
||||
moveAnimation.beginTime = CACurrentMediaTime() + stayTime;
|
||||
moveAnimation.duration = 0.5;
|
||||
moveAnimation.repeatCount = 1;
|
||||
moveAnimation.removedOnCompletion = YES;
|
||||
@kWeakify(self);
|
||||
[moveAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
|
||||
@kStrongify(self);
|
||||
if (finished) {
|
||||
[view removeFromSuperview];
|
||||
[self.giftBroadcastQueue removeObjectAtIndex:0];
|
||||
if (self.giftBroadcastQueue.count > 0) {
|
||||
[self createGiftBroadcastViewAnimation:self.giftBroadcastQueue.firstObject];
|
||||
}
|
||||
}
|
||||
}];
|
||||
|
||||
[view pop_addAnimation:moveAnimation forKey:@"moveOutAnimation"];
|
||||
}
|
||||
|
||||
#pragma mark - XPRoomGiftBroadcastViewDelegate
|
||||
- (void)xPRoomGiftBroadcastView:(XPRoomGiftBroadcastView *)view enterRoom:(NSString *)roomUid {
|
||||
/// TODO: 退出当前房间 换个房间
|
||||
}
|
||||
|
||||
- (void)xPRoomGiftBroadcastView:(XPRoomGiftBroadcastView *)view didClickClose:(XPRoomGiftBroadCastModel *)broadcastModel {
|
||||
[view removeFromSuperview];
|
||||
[view pop_removeAllAnimations];
|
||||
if ([self.giftBroadcastQueue containsObject:broadcastModel]) {
|
||||
[self.giftBroadcastQueue removeObject:broadcastModel];
|
||||
}
|
||||
if (self.giftBroadcastQueue.count > 0) {
|
||||
[self createGiftBroadcastViewAnimation:self.giftBroadcastQueue.firstObject];
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - 福袋中 四级奖品
|
||||
- (void)receiveLuckyGiftBigPrize:(AttachmentModel *)attachment {
|
||||
if (attachment.second == Custom_Message_Sub_Room_Gift_LuckBag || attachment.second == Custom_Message_Sub_Room_Gift_LuckBag_Server) {
|
||||
XPGiftBigPrizeModel * prizeModel = [[XPGiftBigPrizeModel alloc] init];
|
||||
prizeModel.giftName = attachment.data[@"giftName"];
|
||||
prizeModel.luckyBagName = attachment.data[@"luckyBagName"];
|
||||
prizeModel.nick = attachment.data[@"nick"];
|
||||
[self.bigPrizeGiftQueue addObject:prizeModel];
|
||||
if (self.luckyprizeTimer == nil) {
|
||||
[self startHandleBigPrizeGiftTimer];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)startHandleBigPrizeGiftTimer {
|
||||
NSTimeInterval period = 1.0; //设置时间间隔
|
||||
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
|
||||
dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
|
||||
dispatch_source_set_timer(_timer, dispatch_walltime(NULL, 0), period * NSEC_PER_SEC, 0); //每秒执行
|
||||
@kWeakify(self);
|
||||
dispatch_source_set_event_handler(_timer, ^{
|
||||
@kStrongify(self)
|
||||
if (self.bigPrizeGiftQueue.count > 0) {
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
XPGiftBigPrizeModel * prizeModel = [self.bigPrizeGiftQueue firstObject];
|
||||
[self createBigPrizeAnimation:prizeModel];
|
||||
[self.bigPrizeGiftQueue removeObject:prizeModel];
|
||||
});
|
||||
}else {
|
||||
dispatch_source_cancel(_timer);
|
||||
self.luckyprizeTimer = nil;
|
||||
}
|
||||
});
|
||||
dispatch_resume(_timer);
|
||||
self.luckyprizeTimer = _timer;
|
||||
}
|
||||
|
||||
- (void)createBigPrizeAnimation:(XPGiftBigPrizeModel *)prizeModel {
|
||||
NSAttributedString *text = [self createBigPrizeAttribute:prizeModel];
|
||||
UIImageView *luckyBgView = [[UIImageView alloc] initWithFrame:CGRectMake(KScreenWidth, kNavigationHeight + 15, KScreenWidth, 45)];
|
||||
luckyBgView.contentMode = UIViewContentModeScaleAspectFill;
|
||||
luckyBgView.image= [UIImage imageNamed:@"room_lucky_gift_big_prize_bg"];
|
||||
UILabel *contentLabel = [[UILabel alloc] initWithFrame:CGRectMake(90, 0, KScreenWidth - 160, 45)];
|
||||
contentLabel.attributedText = text;
|
||||
contentLabel.textAlignment = NSTextAlignmentCenter;
|
||||
contentLabel.numberOfLines = 2;
|
||||
[luckyBgView addSubview:contentLabel];
|
||||
[self.lowLevelView addSubview:luckyBgView];
|
||||
[UIView animateWithDuration:0.5 animations:^{
|
||||
luckyBgView.frame = CGRectMake(0, kNavigationHeight + 15, KScreenWidth, 45);
|
||||
} completion:^(BOOL finished) {
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(3.0 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
[UIView animateWithDuration:0.5 animations:^{
|
||||
luckyBgView.hidden = YES;
|
||||
} completion:^(BOOL finished) {
|
||||
[luckyBgView removeFromSuperview];
|
||||
}];
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
- (NSAttributedString *)createBigPrizeAttribute:(XPGiftBigPrizeModel *)prizModel {
|
||||
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] init];
|
||||
[attributedString appendAttributedString:
|
||||
[self createTextAttribute:@"哇偶 ! "
|
||||
color:[ThemeColor messageViewTipColor] font:12]];
|
||||
[attributedString appendAttributedString:
|
||||
[self createTextAttribute:prizModel.nick
|
||||
color:[ThemeColor messageNickColor] font:12]];
|
||||
|
||||
[attributedString appendAttributedString:
|
||||
[self createTextAttribute:@"通过"
|
||||
color:[ThemeColor messageViewTipColor] font:12]];
|
||||
|
||||
[attributedString appendAttributedString:
|
||||
[self createTextAttribute:prizModel.luckyBagName
|
||||
color:[ThemeColor messageNickColor] font:12]];
|
||||
|
||||
[attributedString appendAttributedString:
|
||||
[self createTextAttribute:@"开出了"
|
||||
color:[ThemeColor messageNickColor] font:12]];
|
||||
|
||||
[attributedString appendAttributedString:
|
||||
[self createTextAttribute:prizModel.giftName color:[ThemeColor messageNickColor] font:12]];
|
||||
return attributedString;
|
||||
}
|
||||
|
||||
/// 生成一个富文本
|
||||
/// @param text 富文本的文字
|
||||
/// @param color 文字的颜色
|
||||
/// @param font 文字的大小
|
||||
- (NSMutableAttributedString *)createTextAttribute:(NSString *)text color:(UIColor *)color font:(CGFloat)font {
|
||||
if (text == nil || text.length <= 0) {
|
||||
text = @"";
|
||||
}
|
||||
NSDictionary * dic = @{NSFontAttributeName:[UIFont systemFontOfSize:12], NSForegroundColorAttributeName:color};
|
||||
NSMutableAttributedString *attribute = [[NSMutableAttributedString alloc] initWithString:text attributes:dic];
|
||||
return attribute;
|
||||
}
|
||||
|
||||
#pragma mark - 普通礼物
|
||||
///收到了礼物
|
||||
- (void)receiveGift:(GiftReceiveInfoModel *)receiveInfo {
|
||||
///CPU警告的时候 需要停止接收动画
|
||||
///TODO:
|
||||
RoomInfoModel * roomInfor = [self.delegate getRoomInfo];
|
||||
if (receiveInfo.isLuckyBagGift) {
|
||||
//如果是福袋礼物的话 就不用看他的价值了 只要有SVGA的话 就播放
|
||||
if (receiveInfo.displayGift.count > 0) {
|
||||
[receiveInfo.displayGift enumerateObjectsUsingBlock:^(GiftInfoModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
if (obj.hasVggPic && roomInfor.hasAnimationEffect) {
|
||||
GiftReceiveInfoModel * model = [[GiftReceiveInfoModel alloc] init];
|
||||
model.vggUrl = obj.vggUrl;
|
||||
[self.giftEffectQueue addObject:model];
|
||||
}
|
||||
}];
|
||||
}
|
||||
} else {
|
||||
GiftInfoModel *giftInfo = receiveInfo.gift == nil ? receiveInfo.gift : receiveInfo.giftInfo;
|
||||
if (!giftInfo) {
|
||||
giftInfo = [[XPGiftStorage shareStorage] findGiftInfo: receiveInfo.giftId];
|
||||
}
|
||||
///重新赋值一下 用的时候不用在查找了 真的没有的话 那就没有那个礼物了
|
||||
if (giftInfo) {
|
||||
receiveInfo.gift = giftInfo;
|
||||
}
|
||||
if (receiveInfo.targetUsers.count > 0 && receiveInfo.targetUids.count <= 0) {
|
||||
receiveInfo.targetUids = [receiveInfo.targetUsers valueForKeyPath:@"uid"];
|
||||
}
|
||||
|
||||
NSInteger giftTotal = 0;
|
||||
if (receiveInfo.targetUids.count > 0) {
|
||||
giftTotal = receiveInfo.giftNum * giftInfo.goldPrice * receiveInfo.targetUids.count;
|
||||
} else {
|
||||
giftTotal = receiveInfo.giftNum * giftInfo.goldPrice;
|
||||
}
|
||||
|
||||
///房间横幅
|
||||
if (giftTotal >= 520) {
|
||||
///房间横幅和 房间特效的关闭没有关系
|
||||
[self.giftEffectQueue addObject:receiveInfo];
|
||||
} else {
|
||||
///SVGA动画
|
||||
if (giftInfo.hasVggPic && roomInfor.hasAnimationEffect) {
|
||||
receiveInfo.vggUrl = giftInfo.vggUrl;
|
||||
[self.giftEffectQueue addObject:receiveInfo];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (self.giftEffectTimer == nil && self.giftEffectQueue.count > 0) {
|
||||
[self startHandleGiftEffectTimer];
|
||||
}
|
||||
}
|
||||
|
||||
///开启普通礼物特效定时器
|
||||
- (void)startHandleGiftEffectTimer {
|
||||
NSTimeInterval period = 6.0; //设置时间间隔 6秒是 1、单纯的svga 2.有横幅有svga 3、只有横幅
|
||||
dispatch_queue_t queue = dispatch_get_global_queue(0, 0);
|
||||
dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
|
||||
dispatch_source_set_timer(_timer, dispatch_walltime(NULL, 0), period * NSEC_PER_SEC, 0); //每秒执行
|
||||
@kWeakify(self);
|
||||
dispatch_source_set_event_handler(_timer, ^{
|
||||
@kStrongify(self)
|
||||
if (self.giftEffectQueue.count > 0) {
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
GiftReceiveInfoModel * receiveModel = [self.giftEffectQueue firstObject];
|
||||
[self createGiftBannerViewAnimation:receiveModel];
|
||||
[self.giftEffectQueue removeObject:receiveModel];
|
||||
});
|
||||
}else {
|
||||
dispatch_source_cancel(_timer);
|
||||
self.giftEffectTimer = nil;
|
||||
}
|
||||
});
|
||||
dispatch_resume(_timer);
|
||||
self.giftEffectTimer = _timer;
|
||||
}
|
||||
|
||||
- (void)createGiftBannerViewAnimation:(GiftReceiveInfoModel *)receiveInfo {
|
||||
GiftInfoModel * giftInfo = receiveInfo.gift;
|
||||
NSInteger giftTotal = 0;
|
||||
if (receiveInfo.targetUids.count > 0) {
|
||||
giftTotal = receiveInfo.giftNum * giftInfo.goldPrice * receiveInfo.targetUids.count;
|
||||
} else {
|
||||
giftTotal = receiveInfo.giftNum * giftInfo.goldPrice;
|
||||
}
|
||||
if (giftTotal >= 520) {
|
||||
__block XPRoomGiftBannerView *view = [self.bannerDequePool anyObject];
|
||||
if (view == nil) {
|
||||
view = [[XPRoomGiftBannerView alloc] init];
|
||||
[self.bannerVisiablePool addObject:view];
|
||||
}else{
|
||||
[self.bannerDequePool removeObject:view];
|
||||
}
|
||||
[self removeGiftBannerView:view];
|
||||
[view configGiftBanner:receiveInfo users:[self makeBannerUsers]];
|
||||
view.frame = CGRectMake(KScreenWidth, 100, KScreenWidth, 153);
|
||||
[self.lowLevelView addSubview:view];
|
||||
POPSpringAnimation *springAnimation = [POPSpringAnimation animationWithPropertyNamed:kPOPViewCenter];
|
||||
springAnimation.springSpeed = 12;
|
||||
springAnimation.springBounciness = 10.f;
|
||||
springAnimation.fromValue = [NSValue valueWithCGPoint:view.center];
|
||||
springAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(view.frame.size.width / 2, view.center.y)];
|
||||
@kWeakify(self);
|
||||
[springAnimation setCompletionBlock:^(POPAnimation *anim, BOOL finished) {
|
||||
@kStrongify(self);
|
||||
if (finished) {
|
||||
[self removeAnimation:view];
|
||||
}
|
||||
}];
|
||||
|
||||
[springAnimation setAnimationDidStartBlock:^(POPAnimation *anim) {
|
||||
@kStrongify(self);
|
||||
if (giftInfo.hasVggPic && [self.delegate getRoomInfo].hasAnimationEffect) {
|
||||
[self playGiftEffect:giftInfo.vggUrl];
|
||||
}
|
||||
}];
|
||||
|
||||
[view pop_addAnimation:springAnimation forKey:@"spingOutAnimation"];
|
||||
} else {
|
||||
if (receiveInfo.vggUrl.length > 0) {///如果有特效的话就播放特效
|
||||
[self playGiftEffect:receiveInfo.vggUrl];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//移除特效动画
|
||||
- (void)removeAnimation:(XPRoomGiftBannerView *)view{
|
||||
POPBasicAnimation *moveAnimation = [POPBasicAnimation animationWithPropertyNamed:kPOPViewCenter];
|
||||
moveAnimation.fromValue = [NSValue valueWithCGPoint:view.center];
|
||||
moveAnimation.toValue = [NSValue valueWithCGPoint:CGPointMake(view.center.x - KScreenWidth, view.center.y)];
|
||||
moveAnimation.beginTime = CACurrentMediaTime() +5;
|
||||
moveAnimation.duration = 0.5;
|
||||
moveAnimation.repeatCount = 1;
|
||||
moveAnimation.removedOnCompletion = YES;
|
||||
[view pop_addAnimation:moveAnimation forKey:@"moveOutAnimation"];
|
||||
}
|
||||
|
||||
- (NSArray<XPGiftBannerUserInfoModel *> *)makeBannerUsers {
|
||||
NSArray<MicroQueueModel *> * microArray = [self.delegate getMicroQueue].allValues;
|
||||
NSMutableArray * array = [NSMutableArray array];
|
||||
[microArray enumerateObjectsUsingBlock:^(MicroQueueModel * _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
|
||||
XPGiftBannerUserInfoModel * bannserUser = [[XPGiftBannerUserInfoModel alloc] init];
|
||||
bannserUser.position = obj.microState.position;
|
||||
bannserUser.uid = obj.userInfo.uid;
|
||||
[array addObject:bannserUser];
|
||||
}];
|
||||
return array;
|
||||
}
|
||||
|
||||
|
||||
///播放礼物特效 SVGA的
|
||||
- (void)playGiftEffect:(NSString *)vggUrl {
|
||||
self.giftEffectView.hidden = NO;
|
||||
if (self.giftEffectView.superview == nil) {
|
||||
[self.middleLevelView addSubview:self.giftEffectView];
|
||||
[self.giftEffectView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.center.mas_equalTo(self.lowLevelView);
|
||||
make.width.mas_equalTo(KScreenWidth);
|
||||
make.height.mas_equalTo(KScreenHeight);
|
||||
}];
|
||||
}
|
||||
[self.parser parseWithURL:[NSURL URLWithString:vggUrl] completionBlock:^(SVGAVideoEntity * _Nullable videoItem) {
|
||||
if (videoItem != nil) {
|
||||
CGFloat width = videoItem.videoSize.width;
|
||||
CGFloat height = videoItem.videoSize.height;
|
||||
if (width > height) {
|
||||
self.giftEffectView.contentMode = UIViewContentModeScaleAspectFit;
|
||||
} else {//高大于宽
|
||||
CGFloat resizeH = KScreenWidth * height / width;//按照屏幕的宽度去缩放,获得高度
|
||||
if (resizeH > KScreenHeight) {//如果大于屏幕高度,填充
|
||||
self.giftEffectView.contentMode = UIViewContentModeScaleAspectFill;
|
||||
} else {//小于屏幕高度,
|
||||
self.giftEffectView.contentMode = UIViewContentModeScaleAspectFit;
|
||||
}
|
||||
}
|
||||
self.giftEffectView.alpha = 1;
|
||||
self.giftEffectView.loops = 1;
|
||||
self.giftEffectView.clearsAfterStop = YES;
|
||||
self.giftEffectView.videoItem = videoItem;
|
||||
[self.giftEffectView startAnimation];
|
||||
}
|
||||
} failureBlock:^(NSError * _Nullable error) {
|
||||
|
||||
}];
|
||||
}
|
||||
|
||||
///移除横幅的veiw 添加到复用池中
|
||||
- (void)removeGiftBannerView:(XPRoomGiftBannerView *)view {
|
||||
[view removeFromSuperview];
|
||||
[view resetData];
|
||||
[self.bannerVisiablePool removeObject:view];
|
||||
[self.bannerDequePool addObject:view];
|
||||
///svga的处理
|
||||
[self.giftEffectView stopAnimation];
|
||||
self.giftEffectView.hidden = YES;
|
||||
}
|
||||
#pragma mark -
|
||||
- (void)svgaPlayerDidFinishedAnimation:(SVGAPlayer *)player {
|
||||
if (player == self.giftEffectView) {
|
||||
self.giftEffectView.hidden = YES;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Getters And Setters
|
||||
- (UIImageView *)backImageView {
|
||||
if (!_backImageView) {
|
||||
@@ -548,87 +54,4 @@
|
||||
}
|
||||
return _backImageView;
|
||||
}
|
||||
|
||||
- (SVGAImageView *)giftEffectView {
|
||||
if (!_giftEffectView) {
|
||||
_giftEffectView = [[SVGAImageView alloc]init];
|
||||
_giftEffectView.backgroundColor = [UIColor colorWithWhite:0 alpha:0.5];
|
||||
_giftEffectView.userInteractionEnabled = NO;
|
||||
_giftEffectView.delegate = self;
|
||||
_giftEffectView.hidden = YES;
|
||||
}
|
||||
return _giftEffectView;
|
||||
}
|
||||
|
||||
- (SVGAParser *)parser {
|
||||
if (!_parser) {
|
||||
_parser = [[SVGAParser alloc]init];
|
||||
}
|
||||
return _parser;
|
||||
}
|
||||
|
||||
- (NSMutableArray<GiftReceiveInfoModel *> *)giftEffectQueue {
|
||||
if (!_giftEffectQueue) {
|
||||
_giftEffectQueue = [NSMutableArray array];
|
||||
}
|
||||
return _giftEffectQueue;
|
||||
}
|
||||
|
||||
- (NSMutableArray<XPGiftBigPrizeModel *> *)bigPrizeGiftQueue {
|
||||
if (!_bigPrizeGiftQueue) {
|
||||
_bigPrizeGiftQueue = [NSMutableArray array];
|
||||
}
|
||||
return _bigPrizeGiftQueue;
|
||||
}
|
||||
|
||||
- (NSMutableArray<XPRoomGiftBroadCastModel *> *)giftBroadcastQueue {
|
||||
if (!_giftBroadcastQueue) {
|
||||
_giftBroadcastQueue = [NSMutableArray array];
|
||||
}
|
||||
return _giftBroadcastQueue;
|
||||
}
|
||||
|
||||
- (NSMutableSet *)bannerDequePool {
|
||||
if (!_bannerDequePool) {
|
||||
_bannerDequePool = [NSMutableSet set];
|
||||
}
|
||||
return _bannerDequePool;
|
||||
}
|
||||
- (NSMutableSet *)bannerVisiablePool {
|
||||
if (!_bannerVisiablePool) {
|
||||
_bannerVisiablePool = [NSMutableSet set];
|
||||
}
|
||||
return _bannerVisiablePool;
|
||||
}
|
||||
|
||||
- (XPRoomAnimationHitView *)lowLevelView {
|
||||
if (!_lowLevelView) {
|
||||
_lowLevelView = [[XPRoomAnimationHitView alloc] init];
|
||||
_lowLevelView.backgroundColor = [UIColor clearColor];
|
||||
_lowLevelView.userInteractionEnabled = YES;
|
||||
_lowLevelView.tag = 1000;
|
||||
}
|
||||
return _lowLevelView;
|
||||
}
|
||||
|
||||
- (XPRoomAnimationHitView *)middleLevelView {
|
||||
if (!_middleLevelView) {
|
||||
_middleLevelView = [[XPRoomAnimationHitView alloc] init];
|
||||
_middleLevelView.backgroundColor = [UIColor clearColor];
|
||||
_middleLevelView.userInteractionEnabled = YES;
|
||||
_middleLevelView.tag = 2000;
|
||||
}
|
||||
return _middleLevelView;
|
||||
}
|
||||
|
||||
- (XPRoomAnimationHitView *)highLevleView {
|
||||
if (!_highLevleView) {
|
||||
_highLevleView = [[XPRoomAnimationHitView alloc] init];
|
||||
_highLevleView.backgroundColor = [UIColor clearColor];
|
||||
_highLevleView.userInteractionEnabled = YES;
|
||||
_highLevleView.tag = 3000;
|
||||
}
|
||||
return _highLevleView;
|
||||
}
|
||||
|
||||
@end
|
||||
|
@@ -15,6 +15,8 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
@optional
|
||||
- (NSMutableDictionary<NSString *, MicroQueueModel *>*)getMicroQueue;
|
||||
- (void)onMicroQueueUpdate:(NSMutableDictionary<NSString *, MicroQueueModel *>*)queue;
|
||||
///通过uid获取坑位上人的 中心点
|
||||
- (CGPoint)centerForUserAtUid:(NSString *)uid;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
@@ -20,7 +20,6 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
- (void)exitRoom;
|
||||
- (void)miniRoom;
|
||||
- (UINavigationController *)getCurrentNav;
|
||||
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
@@ -77,7 +77,7 @@
|
||||
|
||||
[self.stackView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.centerX.mas_equalTo(self);
|
||||
make.top.mas_equalTo(self.avatarImageView.mas_bottom).offset(7);
|
||||
make.top.mas_equalTo(self.avatarImageView.mas_bottom).offset(6);
|
||||
}];
|
||||
|
||||
[self.postionLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
|
@@ -71,4 +71,22 @@
|
||||
return ownerHeight + marginV1 + mcHeight + marginH + mcHeight;
|
||||
}
|
||||
|
||||
- (CGPoint)centerForUserAtUid:(NSString *)uid {
|
||||
NSInteger index = [self microIndexByUid:uid];
|
||||
CGPoint point = CGPointZero;
|
||||
if (index == 0) {
|
||||
point = CGPointMake(KScreenWidth / 2, ownerWidth / 2 - 10);
|
||||
}
|
||||
|
||||
if (index >= 1 && index <= 4) {
|
||||
point = CGPointMake(paddingH + (mcWidth + marginH) * (index - 1) + mcWidth / 2, firstRowTop + mcWidth / 2- 10);
|
||||
}
|
||||
|
||||
if (index >= 5 && index <= 9) {
|
||||
point = CGPointMake(paddingH + (mcWidth + marginH) * (index - 4 - 1) + mcWidth / 2, secondRowTop + mcWidth / 2 - 10);
|
||||
}
|
||||
point = [self convertPoint:point toView:nil];
|
||||
return point;
|
||||
}
|
||||
|
||||
@end
|
||||
|
@@ -35,6 +35,10 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
* index 处的坑位点击事件
|
||||
*/
|
||||
- (void)didSelectAtIndex:(NSInteger)index;
|
||||
/**
|
||||
* 根据uid获取当前的view的index 如果uid没在坑位上返回-1
|
||||
*/
|
||||
- (NSInteger)microIndexByUid:(NSString *)uid;
|
||||
@end
|
||||
|
||||
@interface StageView : UIView<StageViewDelegate, RoomGuestDelegate>
|
||||
|
@@ -45,16 +45,6 @@
|
||||
@property (nonatomic, strong) NSMutableDictionary<NSString *, MicroQueueModel *> *micQueue;
|
||||
|
||||
@property (nonatomic, weak) id<RoomHostDelegate> hostDelegate;
|
||||
#pragma mark - 送礼物的动画的
|
||||
///礼物的队列
|
||||
@property (nonatomic,strong) NSMutableArray<GiftReceiveInfoModel *> *giftQueue;
|
||||
///定时器
|
||||
@property (nonatomic ,strong)dispatch_source_t giftTimer;
|
||||
///复用池 应为送礼物的动画是一个很频繁的事情 所以可以减少内存的消耗
|
||||
@property (nonatomic,strong) NSMutableSet<NetImageView *> * giftReuseArray;
|
||||
///可见池
|
||||
@property (nonatomic,strong) NSMutableSet<NetImageView *> * giftVisibleArray;
|
||||
|
||||
//TODO 根据自定义消息 更新房间信息 目前就先先放这里
|
||||
///离开模式
|
||||
@property (nonatomic,assign) BOOL leaveMode;
|
||||
@@ -63,11 +53,6 @@
|
||||
@end
|
||||
|
||||
@implementation StageView
|
||||
|
||||
- (void)dealloc {
|
||||
[NSObject cancelPreviousPerformRequestsWithTarget:self];
|
||||
}
|
||||
|
||||
- (instancetype)initWithDelegate:(id<RoomHostDelegate>)delegate {
|
||||
self = [super init];
|
||||
if (self) {
|
||||
@@ -302,9 +287,7 @@
|
||||
NIMCustomObject *obj = (NIMCustomObject *)message.messageObject;
|
||||
if (obj.attachment != nil && [obj.attachment isKindOfClass:[AttachmentModel class]]) {
|
||||
AttachmentModel *attachment = (AttachmentModel *)obj.attachment;
|
||||
if (attachment.first == CustomMessageType_Gift || attachment.first == CustomMessageType_AllMicroSend) {
|
||||
[self receiveGift:attachment];
|
||||
} else if(attachment.first == CustomMessageType_Queue && attachment.second == Custom_Message_Sub_Queue_Invite) {
|
||||
if(attachment.first == CustomMessageType_Queue && attachment.second == Custom_Message_Sub_Queue_Invite) {
|
||||
NSDictionary * dic = attachment.data;
|
||||
if (((NSString *)dic[@"uid"]).integerValue == self.hostDelegate.getUserInfo.uid) {
|
||||
[self microInvite:dic[@"micPosition"]];
|
||||
@@ -314,18 +297,6 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//发送消息成功回调
|
||||
- (void)sendMessage:(NIMMessage *)message didCompleteWithError:(NSError *)error {
|
||||
NIMCustomObject *obj = (NIMCustomObject *)message.messageObject;
|
||||
if (obj.attachment != nil && [obj.attachment isKindOfClass:[AttachmentModel class]]) {
|
||||
AttachmentModel *attachment = (AttachmentModel *)obj.attachment;
|
||||
if (attachment.first == CustomMessageType_Gift || attachment.first == CustomMessageType_AllMicroSend) {
|
||||
[self receiveGift:attachment];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark - 用户邀请上麦
|
||||
- (void)microInvite:(NSString *)position {
|
||||
if ([self findMicroViewByPosition:position]) {
|
||||
@@ -488,191 +459,13 @@
|
||||
return CGRectZero;
|
||||
}
|
||||
|
||||
#pragma mark - 收到礼物展示动画
|
||||
- (void)receiveGift:(AttachmentModel *)attachment {
|
||||
GiftReceiveInfoModel * receiveInfo = [GiftReceiveInfoModel modelWithJSON:attachment.data];
|
||||
GiftInfoModel * giftInfo = receiveInfo.gift ? receiveInfo.gift : receiveInfo.giftInfo;
|
||||
if (attachment.second == Custom_Message_Sub_AllMicroLuckySend || attachment.second == Custom_Message_Sub_AllBatchMicroLuckySend || attachment.second == Custom_Message_Sub_Gift_LuckySend) {
|
||||
NSString * giftId = [NSString stringWithFormat:@"%ld", receiveInfo.luckyGiftList.giftList.firstObject.giftId];
|
||||
giftInfo = [[XPGiftStorage shareStorage] findGiftInfo:giftId];
|
||||
}
|
||||
if (giftInfo == nil) {
|
||||
giftInfo = [[XPGiftStorage shareStorage] findGiftInfo:receiveInfo.giftId];
|
||||
}
|
||||
|
||||
///在最外面判断是否可以拿到那个礼物 后面使用就不用判断了
|
||||
receiveInfo.gift = giftInfo;
|
||||
receiveInfo.isLuckyBagGift = (attachment.second == Custom_Message_Sub_AllMicroLuckySend || attachment.second == Custom_Message_Sub_AllBatchMicroLuckySend || attachment.second == Custom_Message_Sub_Gift_LuckySend);
|
||||
[self.giftQueue addObject:receiveInfo];
|
||||
if (self.giftTimer == nil && self.giftQueue > 0) {
|
||||
[self startGiftQueueTimer];
|
||||
}
|
||||
}
|
||||
|
||||
//扫描礼物队列
|
||||
- (void)startGiftQueueTimer {
|
||||
NSTimeInterval period = 0.5; //设置时间间隔一个礼物动画的时间
|
||||
dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
|
||||
dispatch_source_set_timer(_timer, DISPATCH_TIME_NOW, period * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
|
||||
dispatch_source_set_event_handler(_timer, ^{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (self.giftQueue.count) {
|
||||
GiftReceiveInfoModel * receiveInfo = self.giftQueue.firstObject;
|
||||
[self handoutGiftDistributeAnimation:receiveInfo];
|
||||
[self.giftQueue removeObject:receiveInfo];
|
||||
}else {
|
||||
dispatch_source_cancel(_timer);
|
||||
self.giftTimer = nil;
|
||||
}
|
||||
});
|
||||
});
|
||||
dispatch_resume(_timer);
|
||||
self.giftTimer = _timer;
|
||||
}
|
||||
|
||||
///处理礼物的分发动画
|
||||
- (void)handoutGiftDistributeAnimation:(GiftReceiveInfoModel *)receiveInfo {
|
||||
GiftInfoModel * giftInfo = receiveInfo.gift;
|
||||
NSString * sendUid = receiveInfo.uid;
|
||||
CGPoint starPoint = [self getGiftAnimationPoint:sendUid isEnd:NO];
|
||||
CGPoint endPoint;
|
||||
if (receiveInfo.targetUids.count > 0) {
|
||||
if (receiveInfo.isLuckyBagGift) {
|
||||
NSString * targetUid = [NSString stringWithFormat:@"%ld", receiveInfo.luckyGiftList.user.uid];
|
||||
endPoint = [self getGiftAnimationPoint:targetUid isEnd:YES];
|
||||
dispatch_time_t timer = dispatch_time(DISPATCH_TIME_NOW, 0.5 * NSEC_PER_SEC);
|
||||
dispatch_after(timer, dispatch_get_main_queue(), ^{
|
||||
[self beginGiftAnimation:giftInfo.giftUrl startPoint:starPoint endPoint:endPoint];
|
||||
});
|
||||
} else {
|
||||
for (NSString *targetUid in receiveInfo.targetUids) {
|
||||
endPoint = [self getGiftAnimationPoint:targetUid isEnd:YES];
|
||||
dispatch_time_t timer = dispatch_time(DISPATCH_TIME_NOW, 0.5 * NSEC_PER_SEC);
|
||||
dispatch_after(timer, dispatch_get_main_queue(), ^{
|
||||
[self beginGiftAnimation:giftInfo.giftUrl startPoint:starPoint endPoint:endPoint];
|
||||
});
|
||||
}
|
||||
}
|
||||
} else {
|
||||
NSString * targetUid = receiveInfo.targetUid;
|
||||
endPoint = [self getGiftAnimationPoint:targetUid isEnd:YES];
|
||||
dispatch_time_t timer = dispatch_time(DISPATCH_TIME_NOW, 0.5 * NSEC_PER_SEC);
|
||||
dispatch_after(timer, dispatch_get_main_queue(), ^{
|
||||
[self beginGiftAnimation:giftInfo.giftUrl startPoint:starPoint endPoint:endPoint];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
///起点
|
||||
- (CGPoint)getGiftAnimationPoint:(NSString *)uid isEnd:(BOOL)isEnd{
|
||||
CGPoint point;///启点
|
||||
- (NSInteger)microIndexByUid:(NSString *)uid {
|
||||
UIView * view = [self findMicroViewByUid:uid];
|
||||
if (view) {
|
||||
point = CGPointMake(view.center.x, view.center.y - 10);;
|
||||
} else {
|
||||
if (isEnd) {
|
||||
point = CGPointMake([UIScreen mainScreen].bounds.size.width /2 + 30, 44);
|
||||
} else {
|
||||
point = CGPointMake([UIScreen mainScreen].bounds.size.width / 2, 44);
|
||||
return [self.microViews indexOfObject:view];
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
point = [self convertPoint:point toView:nil];
|
||||
return point;
|
||||
}
|
||||
|
||||
- (void)beginGiftAnimation:(NSString *)giftUrl startPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint {
|
||||
NetImageView * giftImageView = [self.giftReuseArray anyObject];
|
||||
if (giftImageView == nil) {
|
||||
giftImageView = [[NetImageView alloc]initWithFrame:CGRectMake(0, 0 , 55, 55)];
|
||||
giftImageView.center = startPoint;
|
||||
giftImageView.alpha = 1;
|
||||
giftImageView.layer.anchorPoint = CGPointMake(0.5, 0.5);
|
||||
giftImageView.imageUrl = giftUrl;
|
||||
[self.giftVisibleArray addObject:giftImageView];
|
||||
}else {
|
||||
[self.giftReuseArray removeObject:giftImageView];
|
||||
}
|
||||
giftImageView.imageUrl = giftUrl;
|
||||
UIView * superView = [self.superview viewWithTag:1000];
|
||||
if (superView) {
|
||||
[superView addSubview:giftImageView];
|
||||
} else {
|
||||
[self.superview addSubview:giftImageView];
|
||||
[self.superview bringSubviewToFront:giftImageView];
|
||||
}
|
||||
CAAnimationGroup *group = [self createGiftAnimationStartPoint:startPoint endPoint:endPoint];
|
||||
[giftImageView.layer addAnimation:group forKey:@"giftDisplayViewAnimation"];
|
||||
[self performSelector:@selector(aniationDidFinish:) withObject:giftImageView afterDelay:(3.2+0.25)];
|
||||
}
|
||||
|
||||
/// 图片运动的动画组
|
||||
/// @param startPoint 开始的点
|
||||
/// @param endPoint 结束的点
|
||||
- (CAAnimationGroup *)createGiftAnimationStartPoint:(CGPoint)startPoint endPoint:(CGPoint)endPoint{
|
||||
CGPoint centerPoint = CGPointMake(KScreenWidth / 2, KScreenHeight / 2);
|
||||
CAKeyframeAnimation *animation0 = [CAKeyframeAnimation animation];
|
||||
animation0.duration = 0.8;
|
||||
animation0.keyPath = @"transform.scale";
|
||||
animation0.values = @[@1.0,@1.5,@2.0,@1.5];
|
||||
animation0.repeatCount = 1;
|
||||
animation0.calculationMode = kCAAnimationCubic;
|
||||
animation0.removedOnCompletion = NO;
|
||||
animation0.fillMode = kCAFillModeForwards;
|
||||
|
||||
CAKeyframeAnimation *animation1 = [CAKeyframeAnimation animation];
|
||||
animation1.duration = 0.8;
|
||||
animation1.beginTime = 0.8;
|
||||
animation1.keyPath = @"transform.scale";
|
||||
animation1.values = @[@1.5,@2.0,@2.5,@3.0];
|
||||
animation1.repeatCount = 1;
|
||||
animation1.calculationMode = kCAAnimationCubic;
|
||||
animation1.removedOnCompletion = NO;
|
||||
animation1.fillMode = kCAFillModeForwards;
|
||||
|
||||
|
||||
CAKeyframeAnimation *animation2 = [CAKeyframeAnimation animation];
|
||||
animation2.duration = 0.8;
|
||||
animation2.beginTime = 0.8;
|
||||
animation2.keyPath = @"position";
|
||||
animation2.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];;
|
||||
animation2.values = @[[NSValue valueWithCGPoint:startPoint],[NSValue valueWithCGPoint:CGPointMake(centerPoint.x ,centerPoint.y)]];
|
||||
animation2.repeatCount = 1;
|
||||
animation2.removedOnCompletion = NO;
|
||||
animation2.fillMode = kCAFillModeForwards;
|
||||
|
||||
CAKeyframeAnimation *animation3 = [CAKeyframeAnimation animation];
|
||||
animation3.duration = 0.8;
|
||||
animation3.beginTime = 2.6;//0.8+0.8+1
|
||||
animation3.keyPath = @"transform.scale";
|
||||
animation3.values = @[@3,@2.5,@2,@1.5,@1];
|
||||
animation3.repeatCount = 1;
|
||||
|
||||
CAKeyframeAnimation *animation4 = [CAKeyframeAnimation animation];
|
||||
animation4.duration = 0.8;
|
||||
animation4.beginTime = 2.6;
|
||||
animation4.keyPath = @"position";
|
||||
animation4.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
|
||||
animation4.values = @[[NSValue valueWithCGPoint:CGPointMake(centerPoint.x ,centerPoint.y)],[NSValue valueWithCGPoint:endPoint]];
|
||||
animation4.repeatCount = 1;
|
||||
|
||||
CAAnimationGroup *group = [CAAnimationGroup animation];
|
||||
group.duration = 3.2;
|
||||
group.animations = @[animation0,animation1,animation2, animation3,animation4];
|
||||
group.repeatCount = 1;
|
||||
group.removedOnCompletion = NO;
|
||||
group.fillMode = kCAFillModeForwards;
|
||||
|
||||
return group;
|
||||
}
|
||||
|
||||
- (void)aniationDidFinish:(NetImageView *)giftImageView{
|
||||
[giftImageView removeFromSuperview];
|
||||
giftImageView.image = nil;
|
||||
[self.giftVisibleArray removeObject:giftImageView];
|
||||
[self.giftReuseArray addObject:giftImageView];
|
||||
}
|
||||
|
||||
|
||||
#pragma mark - Private Utils Methods - 以下可以不关注
|
||||
/**
|
||||
* 网易云信的麦序转成坑位的 index
|
||||
@@ -754,26 +547,4 @@
|
||||
}
|
||||
return _micQueue;
|
||||
}
|
||||
|
||||
- (NSMutableArray<GiftReceiveInfoModel *> *)giftQueue {
|
||||
if (!_giftQueue) {
|
||||
_giftQueue = [NSMutableArray array];
|
||||
}
|
||||
return _giftQueue;
|
||||
}
|
||||
|
||||
- (NSMutableSet<NetImageView *> *)giftReuseArray {
|
||||
if (!_giftReuseArray) {
|
||||
_giftReuseArray = [NSMutableSet set];
|
||||
}
|
||||
return _giftReuseArray;
|
||||
}
|
||||
|
||||
- (NSMutableSet<NetImageView *> *)giftVisibleArray {
|
||||
if (!_giftVisibleArray) {
|
||||
_giftVisibleArray = [NSMutableSet set];
|
||||
}
|
||||
return _giftVisibleArray;
|
||||
}
|
||||
|
||||
@end
|
||||
|
@@ -26,6 +26,7 @@
|
||||
#import "RoomHeaderView.h"
|
||||
#import "SocialStageView.h"
|
||||
#import "XPMiniRoomView.h"
|
||||
#import "XPRoomAnimationView.h"
|
||||
///P
|
||||
#import "XPRoomPresenter.h"
|
||||
#import "XPRoomProtocol.h"
|
||||
@@ -46,7 +47,8 @@
|
||||
@property (nonatomic,strong) XPRoomMenuContainerView *menuContainerView;
|
||||
///活动
|
||||
@property (nonatomic,strong) XPRoomActivityContainerView *activityContainerView;
|
||||
|
||||
///动画的view
|
||||
@property (nonatomic,strong) XPRoomAnimationView *animationView;
|
||||
///房间的Uid
|
||||
@property (nonatomic,copy) NSString * roomUid;
|
||||
///用户信息
|
||||
@@ -95,10 +97,6 @@
|
||||
[self.view endEditing:YES];
|
||||
}
|
||||
|
||||
- (void)viewDidLayoutSubviews {
|
||||
[super viewDidLayoutSubviews];
|
||||
[self.backContainerView superViewDidLayoutViews];
|
||||
}
|
||||
|
||||
#pragma mark - Private Method
|
||||
- (void)initSubViews {
|
||||
@@ -108,6 +106,7 @@
|
||||
[self.view addSubview:self.messageContainerView];
|
||||
[self.view addSubview:self.menuContainerView];
|
||||
[self.view addSubview:self.activityContainerView];
|
||||
[self.view addSubview:self.animationView];
|
||||
}
|
||||
|
||||
- (void)initSubViewConstraints {
|
||||
@@ -144,6 +143,10 @@
|
||||
make.bottom.mas_equalTo(self.menuContainerView.mas_top).offset(-5);
|
||||
make.width.mas_equalTo(80);
|
||||
}];
|
||||
|
||||
[self.animationView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.edges.mas_equalTo(self.view);
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)exitOldRoom {
|
||||
@@ -213,6 +216,9 @@
|
||||
[self enterRoomFail];
|
||||
}
|
||||
|
||||
- (CGPoint)centerForUserAtUid:(NSString *)uid {
|
||||
return [self.stageView centerForUserAtUid:uid];
|
||||
}
|
||||
|
||||
#pragma mark - RoomDelegate
|
||||
- (RoomInfoModel *)getRoomInfo {
|
||||
@@ -289,4 +295,11 @@
|
||||
return _activityContainerView;
|
||||
}
|
||||
|
||||
- (XPRoomAnimationView *)animationView {
|
||||
if (!_animationView) {
|
||||
_animationView = [[XPRoomAnimationView alloc] initWithdelegate:self];
|
||||
}
|
||||
return _animationView;
|
||||
}
|
||||
|
||||
@end
|
||||
|
Reference in New Issue
Block a user