fix: 优化送礼的内存效率 |
TODO:调整 combo 时的金币变动效果
This commit is contained in:
@@ -500,6 +500,8 @@
|
|||||||
4C6E1F752CEAEC3C0073D0A3 /* ShoppingMallTagView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C6E1F742CEAEC3C0073D0A3 /* ShoppingMallTagView.m */; };
|
4C6E1F752CEAEC3C0073D0A3 /* ShoppingMallTagView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C6E1F742CEAEC3C0073D0A3 /* ShoppingMallTagView.m */; };
|
||||||
4C6E1F792CEB12780073D0A3 /* UIView+GradientLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C6E1F782CEB12780073D0A3 /* UIView+GradientLayer.m */; };
|
4C6E1F792CEB12780073D0A3 /* UIView+GradientLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C6E1F782CEB12780073D0A3 /* UIView+GradientLayer.m */; };
|
||||||
4C6E1F7C2CEB25B10073D0A3 /* ShoppingMallItemPreview.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C6E1F7B2CEB25B10073D0A3 /* ShoppingMallItemPreview.m */; };
|
4C6E1F7C2CEB25B10073D0A3 /* ShoppingMallItemPreview.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C6E1F7B2CEB25B10073D0A3 /* ShoppingMallItemPreview.m */; };
|
||||||
|
4C71C69F2D069D2B00ECCA24 /* GiftAnimationHelper.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C71C69E2D069D2B00ECCA24 /* GiftAnimationHelper.m */; };
|
||||||
|
4C71C6A22D06DB3D00ECCA24 /* GiftAnimationManager.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C71C6A12D06DB3D00ECCA24 /* GiftAnimationManager.m */; };
|
||||||
4C815A172CFEB758002A46A6 /* SuperBlockViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C815A162CFEB758002A46A6 /* SuperBlockViewController.m */; };
|
4C815A172CFEB758002A46A6 /* SuperBlockViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C815A162CFEB758002A46A6 /* SuperBlockViewController.m */; };
|
||||||
4CC6195A2CEC7770008C1EE8 /* MyDressingDataPresent.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC619592CEC7770008C1EE8 /* MyDressingDataPresent.m */; };
|
4CC6195A2CEC7770008C1EE8 /* MyDressingDataPresent.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC619592CEC7770008C1EE8 /* MyDressingDataPresent.m */; };
|
||||||
4CC6195D2CEC996E008C1EE8 /* MyDressingDataModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC6195C2CEC996E008C1EE8 /* MyDressingDataModel.m */; };
|
4CC6195D2CEC996E008C1EE8 /* MyDressingDataModel.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC6195C2CEC996E008C1EE8 /* MyDressingDataModel.m */; };
|
||||||
@@ -2588,6 +2590,10 @@
|
|||||||
4C6E1F782CEB12780073D0A3 /* UIView+GradientLayer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIView+GradientLayer.m"; sourceTree = "<group>"; };
|
4C6E1F782CEB12780073D0A3 /* UIView+GradientLayer.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = "UIView+GradientLayer.m"; sourceTree = "<group>"; };
|
||||||
4C6E1F7A2CEB25B10073D0A3 /* ShoppingMallItemPreview.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ShoppingMallItemPreview.h; sourceTree = "<group>"; };
|
4C6E1F7A2CEB25B10073D0A3 /* ShoppingMallItemPreview.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ShoppingMallItemPreview.h; sourceTree = "<group>"; };
|
||||||
4C6E1F7B2CEB25B10073D0A3 /* ShoppingMallItemPreview.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ShoppingMallItemPreview.m; sourceTree = "<group>"; };
|
4C6E1F7B2CEB25B10073D0A3 /* ShoppingMallItemPreview.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ShoppingMallItemPreview.m; sourceTree = "<group>"; };
|
||||||
|
4C71C69D2D069D2B00ECCA24 /* GiftAnimationHelper.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GiftAnimationHelper.h; sourceTree = "<group>"; };
|
||||||
|
4C71C69E2D069D2B00ECCA24 /* GiftAnimationHelper.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GiftAnimationHelper.m; sourceTree = "<group>"; };
|
||||||
|
4C71C6A02D06DB3D00ECCA24 /* GiftAnimationManager.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GiftAnimationManager.h; sourceTree = "<group>"; };
|
||||||
|
4C71C6A12D06DB3D00ECCA24 /* GiftAnimationManager.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GiftAnimationManager.m; sourceTree = "<group>"; };
|
||||||
4C815A152CFEB758002A46A6 /* SuperBlockViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SuperBlockViewController.h; sourceTree = "<group>"; };
|
4C815A152CFEB758002A46A6 /* SuperBlockViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = SuperBlockViewController.h; sourceTree = "<group>"; };
|
||||||
4C815A162CFEB758002A46A6 /* SuperBlockViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SuperBlockViewController.m; sourceTree = "<group>"; };
|
4C815A162CFEB758002A46A6 /* SuperBlockViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = SuperBlockViewController.m; sourceTree = "<group>"; };
|
||||||
4CC619582CEC7770008C1EE8 /* MyDressingDataPresent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyDressingDataPresent.h; sourceTree = "<group>"; };
|
4CC619582CEC7770008C1EE8 /* MyDressingDataPresent.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = MyDressingDataPresent.h; sourceTree = "<group>"; };
|
||||||
@@ -8271,6 +8277,10 @@
|
|||||||
E8998D7F28597B0300C68558 /* XPRoomLuckyBigPrizeView.m */,
|
E8998D7F28597B0300C68558 /* XPRoomLuckyBigPrizeView.m */,
|
||||||
E838D99E275E1BF60079E0B5 /* XPRoomAnimationView.h */,
|
E838D99E275E1BF60079E0B5 /* XPRoomAnimationView.h */,
|
||||||
E838D99F275E1BF60079E0B5 /* XPRoomAnimationView.m */,
|
E838D99F275E1BF60079E0B5 /* XPRoomAnimationView.m */,
|
||||||
|
4C71C6A02D06DB3D00ECCA24 /* GiftAnimationManager.h */,
|
||||||
|
4C71C6A12D06DB3D00ECCA24 /* GiftAnimationManager.m */,
|
||||||
|
4C71C69D2D069D2B00ECCA24 /* GiftAnimationHelper.h */,
|
||||||
|
4C71C69E2D069D2B00ECCA24 /* GiftAnimationHelper.m */,
|
||||||
23E9EA782A8385CC00B792F2 /* XPTreasureFairyGiftView.h */,
|
23E9EA782A8385CC00B792F2 /* XPTreasureFairyGiftView.h */,
|
||||||
23E9EA772A8385CB00B792F2 /* XPTreasureFairyGiftView.m */,
|
23E9EA772A8385CB00B792F2 /* XPTreasureFairyGiftView.m */,
|
||||||
E8E21A9928B4BD92008F7C9D /* XPRoomGraffitiGiftAnimationView.h */,
|
E8E21A9928B4BD92008F7C9D /* XPRoomGraffitiGiftAnimationView.h */,
|
||||||
@@ -12378,6 +12388,7 @@
|
|||||||
238B37C52AC55A2C00BFC9D5 /* XPTreasureFairyMoreView.m in Sources */,
|
238B37C52AC55A2C00BFC9D5 /* XPTreasureFairyMoreView.m in Sources */,
|
||||||
E811FFF72742367B00918544 /* XPGiftEmptyCollectionViewCell.m in Sources */,
|
E811FFF72742367B00918544 /* XPGiftEmptyCollectionViewCell.m in Sources */,
|
||||||
189DD67E26E1FD8900AB55B1 /* UIImage+Utils.m in Sources */,
|
189DD67E26E1FD8900AB55B1 /* UIImage+Utils.m in Sources */,
|
||||||
|
4C71C6A22D06DB3D00ECCA24 /* GiftAnimationManager.m in Sources */,
|
||||||
E82D5C73276AE94800858D6D /* CarModel.m in Sources */,
|
E82D5C73276AE94800858D6D /* CarModel.m in Sources */,
|
||||||
E85E7B0B2A4EB0D200B6D00A /* XPGuildSetNamePresenter.m in Sources */,
|
E85E7B0B2A4EB0D200B6D00A /* XPGuildSetNamePresenter.m in Sources */,
|
||||||
E87E62762A3F5907002F68C9 /* XPNewHomePlayTableViewCell.m in Sources */,
|
E87E62762A3F5907002F68C9 /* XPNewHomePlayTableViewCell.m in Sources */,
|
||||||
@@ -12758,6 +12769,7 @@
|
|||||||
E81DCCD0282B63FD0039E5C5 /* XPMomentsRecommendViewController.m in Sources */,
|
E81DCCD0282B63FD0039E5C5 /* XPMomentsRecommendViewController.m in Sources */,
|
||||||
9B7D804A2753783D003DAC0C /* SessionViewController.m in Sources */,
|
9B7D804A2753783D003DAC0C /* SessionViewController.m in Sources */,
|
||||||
E85E7BA92A4EC99300B6D00A /* XPMineConfirmGiveDiamondView.m in Sources */,
|
E85E7BA92A4EC99300B6D00A /* XPMineConfirmGiveDiamondView.m in Sources */,
|
||||||
|
4C71C69F2D069D2B00ECCA24 /* GiftAnimationHelper.m in Sources */,
|
||||||
54C9A1102C3D3E1700C6D970 /* XPMineGameMateOrderView.m in Sources */,
|
54C9A1102C3D3E1700C6D970 /* XPMineGameMateOrderView.m in Sources */,
|
||||||
E85E7BA72A4EC99300B6D00A /* XPMineGiveDiamondPasswordView.m in Sources */,
|
E85E7BA72A4EC99300B6D00A /* XPMineGiveDiamondPasswordView.m in Sources */,
|
||||||
54283CEE2CE48B97009729B5 /* ShoppingMallDataPresent.m in Sources */,
|
54283CEE2CE48B97009729B5 /* ShoppingMallDataPresent.m in Sources */,
|
||||||
|
@@ -21,8 +21,8 @@
|
|||||||
#import "ThirdUserInfo.h"
|
#import "ThirdUserInfo.h"
|
||||||
#import "AccountModel.h"
|
#import "AccountModel.h"
|
||||||
#import "DESEncrypt.h"
|
#import "DESEncrypt.h"
|
||||||
#import <FBSDKCoreKit/FBSDKCoreKit.h>
|
//#import <FBSDKCoreKit/FBSDKCoreKit.h>
|
||||||
#import <FBSDKLoginKit/FBSDKLoginKit.h>
|
//#import <FBSDKLoginKit/FBSDKLoginKit.h>
|
||||||
#import "YuMi-swift.h"
|
#import "YuMi-swift.h"
|
||||||
#import "FeedBackConfigModel.h"
|
#import "FeedBackConfigModel.h"
|
||||||
|
|
||||||
@@ -33,25 +33,25 @@
|
|||||||
- (instancetype)init{
|
- (instancetype)init{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
if(self){
|
if(self){
|
||||||
[[NSNotificationCenter defaultCenter] addObserverForName:FBSDKProfileDidChangeNotification
|
// [[NSNotificationCenter defaultCenter] addObserverForName:FBSDKProfileDidChangeNotification
|
||||||
object:nil
|
// object:nil
|
||||||
queue:[NSOperationQueue mainQueue]
|
// queue:[NSOperationQueue mainQueue]
|
||||||
usingBlock:
|
// usingBlock:
|
||||||
^(NSNotification *notification) {
|
// ^(NSNotification *notification) {
|
||||||
if ([FBSDKProfile currentProfile]) {
|
// if ([FBSDKProfile currentProfile]) {
|
||||||
//获取当前用户名
|
// //获取当前用户名
|
||||||
[FBSDKProfile loadCurrentProfileWithCompletion:
|
// [FBSDKProfile loadCurrentProfileWithCompletion:
|
||||||
^(FBSDKProfile *profile, NSError *error) {
|
// ^(FBSDKProfile *profile, NSError *error) {
|
||||||
if (profile) {
|
// if (profile) {
|
||||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||||
AccountInfoStorage *accountStorage = [AccountInfoStorage instance];
|
// AccountInfoStorage *accountStorage = [AccountInfoStorage instance];
|
||||||
accountStorage.thirdUserInfo.userName = profile.name;
|
// accountStorage.thirdUserInfo.userName = profile.name;
|
||||||
accountStorage.thirdUserInfo.avatarUrl = profile.imageURL.absoluteString;
|
// accountStorage.thirdUserInfo.avatarUrl = profile.imageURL.absoluteString;
|
||||||
});
|
// });
|
||||||
}
|
// }
|
||||||
}];
|
// }];
|
||||||
}
|
// }
|
||||||
}];
|
// }];
|
||||||
}
|
}
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
@@ -200,31 +200,31 @@
|
|||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
-(void)thirdLoginByFBWithPresentingViewController:(UIViewController *)presentingViewController {
|
-(void)thirdLoginByFBWithPresentingViewController:(UIViewController *)presentingViewController {
|
||||||
[FBSDKProfile enableUpdatesOnAccessTokenChange:YES];
|
// [FBSDKProfile enableUpdatesOnAccessTokenChange:YES];
|
||||||
[FBSDKAccessToken setCurrentAccessToken:nil];
|
// [FBSDKAccessToken setCurrentAccessToken:nil];
|
||||||
FBSDKLoginManager *manager = [[FBSDKLoginManager alloc] init];
|
// FBSDKLoginManager *manager = [[FBSDKLoginManager alloc] init];
|
||||||
[manager logOut];
|
// [manager logOut];
|
||||||
[XNDJTDDLoadingTool showOnlyView:kWindow];
|
// [XNDJTDDLoadingTool showOnlyView:kWindow];
|
||||||
@kWeakify(self);
|
// @kWeakify(self);
|
||||||
[manager logInWithPermissions:@[@"public_profile"]
|
// [manager logInWithPermissions:@[@"public_profile"]
|
||||||
fromViewController:presentingViewController
|
// fromViewController:presentingViewController
|
||||||
handler:^(FBSDKLoginManagerLoginResult * _Nullable result, NSError * _Nullable error) {
|
// handler:^(FBSDKLoginManagerLoginResult * _Nullable result, NSError * _Nullable error) {
|
||||||
@kStrongify(self);
|
// @kStrongify(self);
|
||||||
if (error) {
|
// if (error) {
|
||||||
[XNDJTDDLoadingTool hideOnlyView:kWindow];
|
// [XNDJTDDLoadingTool hideOnlyView:kWindow];
|
||||||
[[self getView] showErrorToast:YMLocalizedString(@"LoginPresenter1")];
|
// [[self getView] showErrorToast:YMLocalizedString(@"LoginPresenter1")];
|
||||||
} else if (result.isCancelled) {
|
// } else if (result.isCancelled) {
|
||||||
[XNDJTDDLoadingTool hideOnlyView:kWindow];
|
// [XNDJTDDLoadingTool hideOnlyView:kWindow];
|
||||||
[[self getView] showErrorToast:YMLocalizedString(@"LoginPresenter0")];
|
// [[self getView] showErrorToast:YMLocalizedString(@"LoginPresenter0")];
|
||||||
} else {
|
// } else {
|
||||||
ThirdUserInfo * userInfo = [[ThirdUserInfo alloc] init];
|
// ThirdUserInfo * userInfo = [[ThirdUserInfo alloc] init];
|
||||||
userInfo.openid = result.token.userID;
|
// userInfo.openid = result.token.userID;
|
||||||
userInfo.access_token = result.token.tokenString;
|
// userInfo.access_token = result.token.tokenString;
|
||||||
userInfo.unionid = result.token.userID;
|
// userInfo.unionid = result.token.userID;
|
||||||
[AccountInfoStorage instance].thirdUserInfo = userInfo;
|
// [AccountInfoStorage instance].thirdUserInfo = userInfo;
|
||||||
[self loginWithThirdPartWithType:ThirdLoginType_FB];
|
// [self loginWithThirdPartWithType:ThirdLoginType_FB];
|
||||||
}
|
// }
|
||||||
}];
|
// }];
|
||||||
}
|
}
|
||||||
-(void)thirdLoginByGoogleWithPresentingViewController:(UIViewController *)presentingViewController configuration:(GIDConfiguration *)configuration{
|
-(void)thirdLoginByGoogleWithPresentingViewController:(UIViewController *)presentingViewController configuration:(GIDConfiguration *)configuration{
|
||||||
@kWeakify(self);
|
@kWeakify(self);
|
||||||
|
29
YuMi/Modules/YMRoom/View/AnimationView/GiftAnimationHelper.h
Normal file
29
YuMi/Modules/YMRoom/View/AnimationView/GiftAnimationHelper.h
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
//
|
||||||
|
// GiftAnimationManager.h
|
||||||
|
// YuMi
|
||||||
|
//
|
||||||
|
// Created by P on 2024/12/9.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@interface GiftAnimationHelper : NSObject
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Begins a gift animation from a start point to an end point
|
||||||
|
* @param giftUrl URL of the gift image to display
|
||||||
|
* @param startPoint Starting position of the animation
|
||||||
|
* @param endPoint Ending position of the animation
|
||||||
|
* @param isGiftCombing Flag to determine if this is a combo animation
|
||||||
|
*/
|
||||||
|
- (void)beginGiftAnimation:(NSString *)giftUrl
|
||||||
|
startPoint:(CGPoint)startPoint
|
||||||
|
endPoint:(CGPoint)endPoint
|
||||||
|
isGiftCombing:(BOOL)isGiftCombing
|
||||||
|
toTargetView:(UIView *)targetView;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
335
YuMi/Modules/YMRoom/View/AnimationView/GiftAnimationHelper.m
Normal file
335
YuMi/Modules/YMRoom/View/AnimationView/GiftAnimationHelper.m
Normal file
@@ -0,0 +1,335 @@
|
|||||||
|
//
|
||||||
|
// GiftAnimationManager.m
|
||||||
|
// YuMi
|
||||||
|
//
|
||||||
|
// Created by P on 2024/12/9.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "GiftAnimationHelper.h"
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
static const CGFloat kGiftImageSize = 55.0f;
|
||||||
|
static const CGFloat kStandardAnimationDuration = 3.2f;
|
||||||
|
static const CGFloat kComboAnimationDuration = 1.0f;
|
||||||
|
static const CGFloat kCleanupDelay = 0.25f;
|
||||||
|
|
||||||
|
static const CGFloat kComboInitialScale = 0.4f;
|
||||||
|
static const CGFloat kComboFinalScale = 2.0f;
|
||||||
|
static const CGFloat kComboScaleDuration = 0.1f;
|
||||||
|
static const CGFloat kComboMoveDuration = 0.5f;
|
||||||
|
static const CGFloat kComboTotalDuration = 0.6f;
|
||||||
|
|
||||||
|
static const CGFloat kStandardScaleDuration = 0.8f;
|
||||||
|
static const CGFloat kStandardTotalDuration = 3.2f;
|
||||||
|
static const CGFloat kStandardSecondPhaseDelay = 0.8f;
|
||||||
|
static const CGFloat kStandardFinalPhaseDelay = 2.6f;
|
||||||
|
|
||||||
|
@interface GiftAnimationHelper ()
|
||||||
|
|
||||||
|
@property (nonatomic, strong) NSMutableSet<NetImageView *> *giftReuseArray;
|
||||||
|
@property (nonatomic, strong) NSMutableSet<NetImageView *> *giftVisibleArray;
|
||||||
|
@property (nonatomic, strong) UIView *lowLevelView;
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation GiftAnimationHelper
|
||||||
|
|
||||||
|
- (instancetype)init {
|
||||||
|
if (self = [super init]) {
|
||||||
|
self.giftReuseArray = [NSMutableSet set];
|
||||||
|
self.giftVisibleArray = [NSMutableSet set];
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)beginGiftAnimation:(NSString *)giftUrl
|
||||||
|
startPoint:(CGPoint)startPoint
|
||||||
|
endPoint:(CGPoint)endPoint
|
||||||
|
isGiftCombing:(BOOL)isGiftCombing
|
||||||
|
toTargetView:(UIView *)targetView {
|
||||||
|
// Input validation
|
||||||
|
if (!giftUrl.length || CGPointEqualToPoint(startPoint, endPoint)) {
|
||||||
|
NSLog(@"Invalid input parameters for gift animation");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (targetView == nil) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
self.lowLevelView = targetView;
|
||||||
|
|
||||||
|
// Get or create gift image view
|
||||||
|
NetImageView *giftImageView = [self dequeueGiftImageView];
|
||||||
|
[self configureGiftImageView:giftImageView
|
||||||
|
withGiftUrl:giftUrl
|
||||||
|
startPoint:startPoint];
|
||||||
|
|
||||||
|
// Add to view hierarchy
|
||||||
|
[self.lowLevelView addSubview:giftImageView];
|
||||||
|
|
||||||
|
// Create and apply animation
|
||||||
|
CGFloat animationDuration = isGiftCombing ? kComboAnimationDuration : kStandardAnimationDuration;
|
||||||
|
CAAnimationGroup *animationGroup = isGiftCombing ?
|
||||||
|
[self createGiftComboAnimationStartPoint:startPoint endPoint:endPoint] :
|
||||||
|
[self createGiftAnimationStartPoint:startPoint endPoint:endPoint];
|
||||||
|
|
||||||
|
// Ensure correct starting position
|
||||||
|
giftImageView.layer.position = startPoint;
|
||||||
|
[giftImageView.layer addAnimation:animationGroup forKey:@"giftDisplayViewAnimation"];
|
||||||
|
|
||||||
|
// Schedule cleanup
|
||||||
|
[self performSelector:@selector(animationDidFinish:)
|
||||||
|
withObject:giftImageView
|
||||||
|
afterDelay:(animationDuration + kCleanupDelay)];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NetImageView *)dequeueGiftImageView {
|
||||||
|
NetImageView *giftImageView = [self.giftReuseArray anyObject];
|
||||||
|
if (giftImageView) {
|
||||||
|
[self.giftReuseArray removeObject:giftImageView];
|
||||||
|
} else {
|
||||||
|
giftImageView = [[NetImageView alloc] initWithFrame:CGRectMake(0, 0, kGiftImageSize, kGiftImageSize)];
|
||||||
|
[self.giftVisibleArray addObject:giftImageView];
|
||||||
|
}
|
||||||
|
return giftImageView;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)configureGiftImageView:(NetImageView *)giftImageView
|
||||||
|
withGiftUrl:(NSString *)giftUrl
|
||||||
|
startPoint:(CGPoint)startPoint {
|
||||||
|
giftImageView.center = startPoint;
|
||||||
|
giftImageView.alpha = 1.0;
|
||||||
|
giftImageView.layer.anchorPoint = CGPointMake(0.5, 0.5);
|
||||||
|
giftImageView.imageUrl = giftUrl;
|
||||||
|
giftImageView.hidden = NO;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)animationDidFinish:(NetImageView *)giftImageView {
|
||||||
|
[giftImageView removeFromSuperview];
|
||||||
|
giftImageView.hidden = YES;
|
||||||
|
[self.giftReuseArray addObject:giftImageView];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CAAnimationGroup *)createGiftComboAnimationStartPoint:(CGPoint)startPoint
|
||||||
|
endPoint:(CGPoint)endPoint {
|
||||||
|
// Initial shrink animation
|
||||||
|
CAKeyframeAnimation *initialScale = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"];
|
||||||
|
initialScale.duration = kComboScaleDuration;
|
||||||
|
initialScale.values = @[@1.0, @(kComboInitialScale)];
|
||||||
|
initialScale.repeatCount = 1;
|
||||||
|
initialScale.calculationMode = kCAAnimationCubic;
|
||||||
|
initialScale.removedOnCompletion = NO;
|
||||||
|
initialScale.fillMode = kCAFillModeForwards;
|
||||||
|
|
||||||
|
// Movement animation
|
||||||
|
CAKeyframeAnimation *movement = [CAKeyframeAnimation animationWithKeyPath:@"position"];
|
||||||
|
movement.duration = kComboMoveDuration;
|
||||||
|
movement.beginTime = kComboScaleDuration;
|
||||||
|
movement.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
|
||||||
|
movement.values = @[
|
||||||
|
[NSValue valueWithCGPoint:startPoint],
|
||||||
|
[NSValue valueWithCGPoint:endPoint]
|
||||||
|
];
|
||||||
|
movement.repeatCount = 1;
|
||||||
|
movement.removedOnCompletion = NO;
|
||||||
|
movement.fillMode = kCAFillModeForwards;
|
||||||
|
|
||||||
|
// Growth during movement animation
|
||||||
|
CAKeyframeAnimation *growthDuringMove = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"];
|
||||||
|
growthDuringMove.duration = kComboMoveDuration;
|
||||||
|
growthDuringMove.beginTime = kComboScaleDuration;
|
||||||
|
growthDuringMove.values = @[@(kComboInitialScale), @(kComboFinalScale)];
|
||||||
|
growthDuringMove.repeatCount = 1;
|
||||||
|
growthDuringMove.calculationMode = kCAAnimationCubic;
|
||||||
|
growthDuringMove.removedOnCompletion = NO;
|
||||||
|
growthDuringMove.fillMode = kCAFillModeForwards;
|
||||||
|
|
||||||
|
// Combine animations
|
||||||
|
CAAnimationGroup *group = [CAAnimationGroup animation];
|
||||||
|
group.duration = kComboTotalDuration;
|
||||||
|
group.animations = @[initialScale, movement, growthDuringMove];
|
||||||
|
group.repeatCount = 1;
|
||||||
|
group.removedOnCompletion = NO;
|
||||||
|
group.fillMode = kCAFillModeForwards;
|
||||||
|
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Creates a complex gift animation with multiple phases
|
||||||
|
* @param startPoint Initial position of the gift
|
||||||
|
* @param endPoint Final position of the gift
|
||||||
|
* @return CAAnimationGroup containing multiple scale and position animations
|
||||||
|
*/
|
||||||
|
- (CAAnimationGroup *)createGiftAnimationStartPoint:(CGPoint)startPoint
|
||||||
|
endPoint:(CGPoint)endPoint {
|
||||||
|
CGPoint centerPoint = CGPointMake(KScreenWidth / 2, KScreenHeight / 2);
|
||||||
|
|
||||||
|
// Initial scale up animation
|
||||||
|
CAKeyframeAnimation *initialScale = [CAKeyframeAnimation animation];
|
||||||
|
initialScale.duration = kStandardScaleDuration;
|
||||||
|
initialScale.keyPath = @"transform.scale";
|
||||||
|
initialScale.values = @[@1.0, @1.5, @2.0, @1.5];
|
||||||
|
initialScale.repeatCount = 1;
|
||||||
|
initialScale.calculationMode = kCAAnimationCubic;
|
||||||
|
initialScale.removedOnCompletion = NO;
|
||||||
|
initialScale.fillMode = kCAFillModeForwards;
|
||||||
|
|
||||||
|
// Second phase scale animation
|
||||||
|
CAKeyframeAnimation *secondScale = [CAKeyframeAnimation animation];
|
||||||
|
secondScale.duration = kStandardScaleDuration;
|
||||||
|
secondScale.beginTime = kStandardSecondPhaseDelay;
|
||||||
|
secondScale.keyPath = @"transform.scale";
|
||||||
|
secondScale.values = @[@1.5, @2.0, @2.5, @3.0];
|
||||||
|
secondScale.repeatCount = 1;
|
||||||
|
secondScale.calculationMode = kCAAnimationCubic;
|
||||||
|
secondScale.removedOnCompletion = NO;
|
||||||
|
secondScale.fillMode = kCAFillModeForwards;
|
||||||
|
|
||||||
|
// Move to center animation
|
||||||
|
CAKeyframeAnimation *moveToCenter = [CAKeyframeAnimation animation];
|
||||||
|
moveToCenter.duration = kStandardScaleDuration;
|
||||||
|
moveToCenter.beginTime = kStandardSecondPhaseDelay;
|
||||||
|
moveToCenter.keyPath = @"position";
|
||||||
|
moveToCenter.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
|
||||||
|
moveToCenter.values = @[
|
||||||
|
[NSValue valueWithCGPoint:startPoint],
|
||||||
|
[NSValue valueWithCGPoint:centerPoint]
|
||||||
|
];
|
||||||
|
moveToCenter.repeatCount = 1;
|
||||||
|
moveToCenter.removedOnCompletion = NO;
|
||||||
|
moveToCenter.fillMode = kCAFillModeForwards;
|
||||||
|
|
||||||
|
// Final scale down animation
|
||||||
|
CAKeyframeAnimation *finalScale = [CAKeyframeAnimation animation];
|
||||||
|
finalScale.duration = kStandardScaleDuration;
|
||||||
|
finalScale.beginTime = kStandardFinalPhaseDelay;
|
||||||
|
finalScale.keyPath = @"transform.scale";
|
||||||
|
finalScale.values = @[@3.0, @2.5, @2.0, @1.5, @1.0];
|
||||||
|
finalScale.repeatCount = 1;
|
||||||
|
|
||||||
|
// Move to final position animation
|
||||||
|
CAKeyframeAnimation *moveToEnd = [CAKeyframeAnimation animation];
|
||||||
|
moveToEnd.duration = kStandardScaleDuration;
|
||||||
|
moveToEnd.beginTime = kStandardFinalPhaseDelay;
|
||||||
|
moveToEnd.keyPath = @"position";
|
||||||
|
moveToEnd.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];
|
||||||
|
moveToEnd.values = @[
|
||||||
|
[NSValue valueWithCGPoint:centerPoint],
|
||||||
|
[NSValue valueWithCGPoint:endPoint]
|
||||||
|
];
|
||||||
|
moveToEnd.repeatCount = 1;
|
||||||
|
|
||||||
|
// Combine all animations
|
||||||
|
CAAnimationGroup *group = [CAAnimationGroup animation];
|
||||||
|
group.duration = kStandardTotalDuration;
|
||||||
|
group.animations = @[initialScale, secondScale, moveToCenter, finalScale, moveToEnd];
|
||||||
|
group.repeatCount = 1;
|
||||||
|
group.removedOnCompletion = NO;
|
||||||
|
group.fillMode = kCAFillModeForwards;
|
||||||
|
|
||||||
|
return group;
|
||||||
|
}
|
||||||
|
|
||||||
|
//- (CAAnimationGroup *)createGiftComboAnimationStartPoint:(CGPoint)startPoint
|
||||||
|
// endPoint:(CGPoint)endPoint {
|
||||||
|
// // 缩放动画1: 动画开始时缩放至 0.4
|
||||||
|
// CAKeyframeAnimation *scaleAnimation1 = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"];
|
||||||
|
// scaleAnimation1.duration = 0.1;
|
||||||
|
// scaleAnimation1.values = @[@1.0, @0.4];
|
||||||
|
// scaleAnimation1.repeatCount = 1;
|
||||||
|
// scaleAnimation1.calculationMode = kCAAnimationCubic;
|
||||||
|
// scaleAnimation1.removedOnCompletion = NO;
|
||||||
|
// scaleAnimation1.fillMode = kCAFillModeForwards;
|
||||||
|
//
|
||||||
|
// // 位移动画: 0.5秒内从起点移动到目标点
|
||||||
|
// CAKeyframeAnimation *positionAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
|
||||||
|
// positionAnimation.duration = 0.5;
|
||||||
|
// positionAnimation.beginTime = 0.1; // 缩放结束后开始位移
|
||||||
|
// positionAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
|
||||||
|
// positionAnimation.values = @[[NSValue valueWithCGPoint:startPoint], [NSValue valueWithCGPoint:endPoint]];
|
||||||
|
// positionAnimation.repeatCount = 1;
|
||||||
|
// positionAnimation.removedOnCompletion = NO;
|
||||||
|
// positionAnimation.fillMode = kCAFillModeForwards;
|
||||||
|
//
|
||||||
|
// // 缩放动画2: 在位移的过程中逐渐变大到 1.2
|
||||||
|
// CAKeyframeAnimation *scaleAnimation2 = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"];
|
||||||
|
// scaleAnimation2.duration = 0.5;
|
||||||
|
// scaleAnimation2.beginTime = 0.1; // 同时与位移动画进行
|
||||||
|
// scaleAnimation2.values = @[@0.4, @2];
|
||||||
|
// scaleAnimation2.repeatCount = 1;
|
||||||
|
// scaleAnimation2.calculationMode = kCAAnimationCubic;
|
||||||
|
// scaleAnimation2.removedOnCompletion = NO;
|
||||||
|
// scaleAnimation2.fillMode = kCAFillModeForwards;
|
||||||
|
//
|
||||||
|
// // 创建动画组
|
||||||
|
// CAAnimationGroup *group = [CAAnimationGroup animation];
|
||||||
|
// group.duration = 0.6; // 总时间为 0.1 (缩放) + 0.5 (位移与缩放)
|
||||||
|
// group.animations = @[scaleAnimation1, positionAnimation, scaleAnimation2];
|
||||||
|
// group.repeatCount = 1;
|
||||||
|
// group.removedOnCompletion = NO;
|
||||||
|
// group.fillMode = kCAFillModeForwards;
|
||||||
|
//
|
||||||
|
// return group;
|
||||||
|
//}
|
||||||
|
//
|
||||||
|
///// 图片运动的动画组
|
||||||
|
///// @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;
|
||||||
|
//}
|
||||||
|
|
||||||
|
@end
|
@@ -0,0 +1,57 @@
|
|||||||
|
//
|
||||||
|
// GiftAnimationManager.h
|
||||||
|
// YuMi
|
||||||
|
//
|
||||||
|
// Created by P on 2024/12/9.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import <Foundation/Foundation.h>
|
||||||
|
@class GiftReceiveInfoModel;
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_BEGIN
|
||||||
|
|
||||||
|
@protocol GiftAnimationDelegate <NSObject>
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Returns the animation point for a given user ID in the stage view
|
||||||
|
* @param uid The user ID to get the animation point for
|
||||||
|
* @return CGPoint The point in the view's coordinate system where the animation should occur
|
||||||
|
*/
|
||||||
|
- (CGPoint)animationPointAtStageViewByUid:(NSString *)uid;
|
||||||
|
|
||||||
|
@optional
|
||||||
|
/**
|
||||||
|
* Called when a gift animation starts
|
||||||
|
* @param giftInfo The gift information model
|
||||||
|
*/
|
||||||
|
//- (void)didStartGiftAnimation:(GiftInfoModel *)giftInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when a gift animation completes
|
||||||
|
* @param giftInfo The gift information model
|
||||||
|
*/
|
||||||
|
//- (void)didCompleteGiftAnimation:(GiftInfoModel *)giftInfo;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Called when the gift queue becomes empty
|
||||||
|
*/
|
||||||
|
- (void)didEmptyGiftQueue;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@interface GiftAnimationManager : NSObject
|
||||||
|
@property (nonatomic, weak) id<GiftAnimationDelegate> delegate;
|
||||||
|
@property (nonatomic, strong) UIView *containerView;
|
||||||
|
|
||||||
|
// Configurable properties
|
||||||
|
@property (nonatomic, assign) NSTimeInterval animationInterval;
|
||||||
|
@property (nonatomic, assign) NSTimeInterval comboAnimationDelay;
|
||||||
|
@property (nonatomic, assign) NSTimeInterval standardAnimationDelay;
|
||||||
|
|
||||||
|
- (instancetype)initWithContainerView:(UIView *)containerView;
|
||||||
|
- (void)enqueueGift:(GiftReceiveInfoModel *)giftInfo;
|
||||||
|
- (void)startGiftQueue;
|
||||||
|
- (void)stopGiftQueue;
|
||||||
|
@end
|
||||||
|
|
||||||
|
NS_ASSUME_NONNULL_END
|
195
YuMi/Modules/YMRoom/View/AnimationView/GiftAnimationManager.m
Normal file
195
YuMi/Modules/YMRoom/View/AnimationView/GiftAnimationManager.m
Normal file
@@ -0,0 +1,195 @@
|
|||||||
|
//
|
||||||
|
// GiftAnimationManager.m
|
||||||
|
// YuMi
|
||||||
|
//
|
||||||
|
// Created by P on 2024/12/9.
|
||||||
|
//
|
||||||
|
|
||||||
|
#import "GiftAnimationManager.h"
|
||||||
|
|
||||||
|
#import "GiftComboManager.h"
|
||||||
|
#import "GiftAnimationHelper.h"
|
||||||
|
#import "GiftReceiveInfoModel.h"
|
||||||
|
|
||||||
|
@interface GiftAnimationManager ()
|
||||||
|
|
||||||
|
@property (nonatomic, strong) dispatch_source_t giftTimer;
|
||||||
|
@property (nonatomic, strong) NSMutableArray<GiftReceiveInfoModel *> *giftQueue;
|
||||||
|
@property (nonatomic, strong) GiftAnimationHelper *animationHelper;
|
||||||
|
|
||||||
|
@end
|
||||||
|
|
||||||
|
@implementation GiftAnimationManager
|
||||||
|
|
||||||
|
- (instancetype)initWithContainerView:(UIView *)containerView {
|
||||||
|
self = [super init];
|
||||||
|
if (self) {
|
||||||
|
_containerView = containerView;
|
||||||
|
_giftQueue = [NSMutableArray array];
|
||||||
|
_animationHelper = [[GiftAnimationHelper alloc] init];
|
||||||
|
_animationInterval = 0.25;
|
||||||
|
_comboAnimationDelay = 0.25;
|
||||||
|
_standardAnimationDelay = 0.5;
|
||||||
|
}
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)startGiftQueue {
|
||||||
|
if (self.giftTimer) return;
|
||||||
|
|
||||||
|
dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,
|
||||||
|
dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
|
||||||
|
|
||||||
|
dispatch_source_set_timer(timer,
|
||||||
|
DISPATCH_TIME_NOW,
|
||||||
|
self.animationInterval * NSEC_PER_SEC,
|
||||||
|
0);
|
||||||
|
|
||||||
|
@kWeakify(self);
|
||||||
|
dispatch_source_set_event_handler(timer, ^{
|
||||||
|
dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
|
@kStrongify(self);
|
||||||
|
[self processNextGift];
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
dispatch_resume(timer);
|
||||||
|
self.giftTimer = timer;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)processNextGift {
|
||||||
|
if (self.giftQueue.count == 0) {
|
||||||
|
[self stopGiftQueue];
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
GiftReceiveInfoModel *giftInfo = self.giftQueue.firstObject;
|
||||||
|
[self distributeGiftAnimation:giftInfo];
|
||||||
|
[self.giftQueue removeObjectAtIndex:0];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)distributeGiftAnimation:(GiftReceiveInfoModel *)giftInfo {
|
||||||
|
NSArray<NSString *> *targetUids = [self resolveTargetUids:giftInfo];
|
||||||
|
CGPoint startPoint = [self calculateAnimationPoint:giftInfo.uid isEndPoint:NO];
|
||||||
|
|
||||||
|
BOOL isComboAnimation = [self shouldUseComboAnimationForSender:giftInfo.uid];
|
||||||
|
NSTimeInterval delay = isComboAnimation ? self.comboAnimationDelay : self.standardAnimationDelay;
|
||||||
|
|
||||||
|
for (NSString *targetUid in targetUids) {
|
||||||
|
CGPoint endPoint = [self calculateAnimationPoint:targetUid isEndPoint:YES];
|
||||||
|
[self scheduleAnimationWithDelay:delay
|
||||||
|
giftInfo:giftInfo.gift
|
||||||
|
startPoint:startPoint
|
||||||
|
endPoint:endPoint
|
||||||
|
isComboAnimation:isComboAnimation];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray<NSString *> *)resolveTargetUids:(GiftReceiveInfoModel *)giftInfo {
|
||||||
|
if (giftInfo.isLuckyBagGift) {
|
||||||
|
return @[giftInfo.targetUid];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (giftInfo.targetUids.count > 0) {
|
||||||
|
return [giftInfo.targetUids valueForKey:@"stringValue"];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (giftInfo.targetUsers) {
|
||||||
|
NSArray *uidDatas = [self ensureArrayContainsOnlyStrings:[giftInfo.targetUsers valueForKeyPath:@"uid"]];
|
||||||
|
|
||||||
|
return uidDatas;//[giftInfo.targetUsers valueForKeyPath:@"uid"];
|
||||||
|
}
|
||||||
|
|
||||||
|
return [NSString isEmpty:giftInfo.targetUid] ? @[] : @[giftInfo.targetUid];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (NSArray<NSString *> *)ensureArrayContainsOnlyStrings:(NSArray *)inputArray {
|
||||||
|
// 用于存放最终结果
|
||||||
|
NSMutableArray<NSString *> *resultArray = [NSMutableArray array];
|
||||||
|
|
||||||
|
for (id item in inputArray) {
|
||||||
|
if ([item isKindOfClass:[NSString class]]) {
|
||||||
|
// 如果是 NSString,直接添加到结果数组
|
||||||
|
[resultArray addObject:item];
|
||||||
|
} else if ([item isKindOfClass:[NSNumber class]]) {
|
||||||
|
// 如果是 NSNumber,转换为 NSString 后添加
|
||||||
|
[resultArray addObject:[item stringValue]];
|
||||||
|
} else {
|
||||||
|
// 对于非 NSString 或 NSNumber 的类型,可以选择忽略或者抛出异常
|
||||||
|
NSLog(@"Warning: Unsupported item type: %@", [item class]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return [resultArray copy]; // 返回不可变数组
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGPoint)calculateAnimationPoint:(NSString *)uid isEndPoint:(BOOL)isEndPoint {
|
||||||
|
CGPoint point = [self.delegate animationPointAtStageViewByUid:uid];
|
||||||
|
|
||||||
|
if (point.x <= 0 || point.y <= 0) {
|
||||||
|
point = [self fallbackPointForEndPoint:isEndPoint];
|
||||||
|
}
|
||||||
|
|
||||||
|
if ([self shouldUseComboAnimationForSender:uid] && !isEndPoint) {
|
||||||
|
point = [self comboAnimationStartPoint];
|
||||||
|
}
|
||||||
|
|
||||||
|
return point;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)scheduleAnimationWithDelay:(NSTimeInterval)delay
|
||||||
|
giftInfo:(GiftInfoModel *)giftInfo
|
||||||
|
startPoint:(CGPoint)startPoint
|
||||||
|
endPoint:(CGPoint)endPoint
|
||||||
|
isComboAnimation:(BOOL)isComboAnimation {
|
||||||
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, delay * NSEC_PER_SEC),
|
||||||
|
dispatch_get_main_queue(), ^{
|
||||||
|
[self.animationHelper beginGiftAnimation:giftInfo.giftUrl
|
||||||
|
startPoint:startPoint
|
||||||
|
endPoint:endPoint
|
||||||
|
isGiftCombing:isComboAnimation
|
||||||
|
toTargetView:self.containerView];
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)stopGiftQueue {
|
||||||
|
if (self.giftTimer) {
|
||||||
|
dispatch_source_cancel(self.giftTimer);
|
||||||
|
self.giftTimer = nil;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)enqueueGift:(GiftReceiveInfoModel *)giftInfo {
|
||||||
|
[self.giftQueue addObject:giftInfo];
|
||||||
|
[self startGiftQueue];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper methods
|
||||||
|
- (BOOL)shouldUseComboAnimationForSender:(NSString *)uid {
|
||||||
|
return [[GiftComboManager sharedManager] isGiftCombing] &&
|
||||||
|
[uid isEqualToString:[AccountInfoStorage instance].getUid];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGPoint)fallbackPointForEndPoint:(BOOL)isEndPoint {
|
||||||
|
CGFloat x = [UIScreen mainScreen].bounds.size.width / 2;
|
||||||
|
if (isEndPoint) {
|
||||||
|
x += 30;
|
||||||
|
}
|
||||||
|
return CGPointMake(x, 44 + kSafeAreaTopHeight);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (CGPoint)comboAnimationStartPoint {
|
||||||
|
if (isMSRTL()) {
|
||||||
|
return CGPointMake(kGetScaleWidth(86),
|
||||||
|
[UIScreen mainScreen].bounds.size.height - kSafeAreaTopHeight - kGetScaleWidth(140));
|
||||||
|
}
|
||||||
|
|
||||||
|
CGFloat x = KScreenWidth <= 375 ?
|
||||||
|
[UIScreen mainScreen].bounds.size.width - kGetScaleWidth(86) :
|
||||||
|
[UIScreen mainScreen].bounds.size.width - kGetScaleWidth(120);
|
||||||
|
|
||||||
|
return CGPointMake(x,
|
||||||
|
[UIScreen mainScreen].bounds.size.height - kSafeAreaBottomHeight - kGetScaleWidth(140));
|
||||||
|
}
|
||||||
|
|
||||||
|
@end
|
@@ -13,36 +13,40 @@
|
|||||||
#import "XPRoomViewController.h"
|
#import "XPRoomViewController.h"
|
||||||
#import "XCCurrentVCStackManager.h"
|
#import "XCCurrentVCStackManager.h"
|
||||||
|
|
||||||
|
// Constants
|
||||||
|
static const CGFloat kBannerWidth = 346.5f;
|
||||||
|
static const CGFloat kBannerHeight = 82.5f;
|
||||||
|
static const CGFloat kBannerTopMargin = 80.0f;
|
||||||
|
static const CGFloat kAvatarSize = 43.0f;
|
||||||
|
static const CGFloat kAnimationDuration = 0.25f;
|
||||||
|
static const CGFloat kDisplayDuration = 2.5f;
|
||||||
|
static const CGFloat kRoomTransitionDelay = 2.0f;
|
||||||
|
|
||||||
@interface LuckyGiftWinningBannerViewModel : PIBaseModel
|
@interface LuckyGiftWinningBannerViewModel : PIBaseModel
|
||||||
|
|
||||||
// 会命中混淆,model 单独出来
|
@property (nonatomic, copy, readonly) NSString *times;
|
||||||
@property (nonatomic, copy) NSString *times;
|
@property (nonatomic, copy, readonly) NSString *avatar;
|
||||||
@property (nonatomic, copy) NSString *avatar;
|
@property (nonatomic, copy, readonly) NSString *coins;
|
||||||
@property (nonatomic, copy) NSString *coins;
|
@property (nonatomic, copy, readonly) NSDictionary *giftNameMap;
|
||||||
@property (nonatomic, copy) NSDictionary *giftNameMap;
|
@property (nonatomic, copy, readonly) NSString *roomUid;
|
||||||
@property (nonatomic, copy) NSString *roomUid;
|
@property (nonatomic, copy, readonly) NSString *giftName;
|
||||||
|
|
||||||
- (NSString *)giftName;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
|
|
||||||
@implementation LuckyGiftWinningBannerViewModel
|
@implementation LuckyGiftWinningBannerViewModel
|
||||||
|
|
||||||
+ (NSDictionary *)replacedKeyFromPropertyName {
|
+ (NSDictionary *)replacedKeyFromPropertyName {
|
||||||
return @{
|
return @{@"avatar": @"sender.avatar"};
|
||||||
@"avatar":@"sender.avatar"
|
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSString *)giftName {
|
- (NSString *)giftName {
|
||||||
if ([self.giftNameMap.allKeys containsObject:@"ar"] && isMSRTL()) {
|
if (isMSRTL() && [self.giftNameMap[@"ar"] length]) {
|
||||||
return self.giftNameMap[@"ar"];
|
return self.giftNameMap[@"ar"];
|
||||||
} else if ([self.giftNameMap.allKeys containsObject:@"zh"] && isMSZH()) {
|
|
||||||
return self.giftNameMap[@"zh"];
|
|
||||||
} else {
|
|
||||||
return self.giftNameMap[@"en"];
|
|
||||||
}
|
}
|
||||||
|
if (isMSZH() && [self.giftNameMap[@"zh"] length]) {
|
||||||
|
return self.giftNameMap[@"zh"];
|
||||||
|
}
|
||||||
|
return self.giftNameMap[@"en"] ?: @"";
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
@@ -52,13 +56,11 @@
|
|||||||
@property (nonatomic, strong) LuckyGiftWinningBannerViewModel *model;
|
@property (nonatomic, strong) LuckyGiftWinningBannerViewModel *model;
|
||||||
@property (nonatomic, strong) UIImageView *backgroundImageView;
|
@property (nonatomic, strong) UIImageView *backgroundImageView;
|
||||||
@property (nonatomic, strong) UIImageView *ballImageView;
|
@property (nonatomic, strong) UIImageView *ballImageView;
|
||||||
@property (nonatomic, strong) NetImageView *avatarImage;
|
@property (nonatomic, strong) NetImageView *avatarImageView;
|
||||||
@property (nonatomic, strong) UILabel *giftNameLabel;
|
@property (nonatomic, strong) UILabel *giftNameLabel;
|
||||||
@property (nonatomic, strong) UILabel *timesLabel;
|
@property (nonatomic, strong) UILabel *timesLabel;
|
||||||
@property (nonatomic, strong) UILabel *coinsLabel;
|
@property (nonatomic, strong) UILabel *coinsLabel;
|
||||||
|
|
||||||
@property (nonatomic, assign) NSInteger currentRoomUid;
|
@property (nonatomic, assign) NSInteger currentRoomUid;
|
||||||
|
|
||||||
@property (nonatomic, copy) void(^completeDisplay)(void);
|
@property (nonatomic, copy) void(^completeDisplay)(void);
|
||||||
@property (nonatomic, copy) void(^exitCurrentRoom)(void);
|
@property (nonatomic, copy) void(^exitCurrentRoom)(void);
|
||||||
|
|
||||||
@@ -71,39 +73,66 @@
|
|||||||
with:(AttachmentModel *)attachment
|
with:(AttachmentModel *)attachment
|
||||||
complete:(void(^)(void))complete
|
complete:(void(^)(void))complete
|
||||||
exitCurrentRoom:(void(^)(void))exit {
|
exitCurrentRoom:(void(^)(void))exit {
|
||||||
|
#if DEBUG
|
||||||
|
NSParameterAssert(superView);
|
||||||
|
NSParameterAssert(attachment);
|
||||||
|
#else
|
||||||
|
if (!superView || !attachment) {
|
||||||
|
if (complete) {
|
||||||
|
complete();
|
||||||
|
}
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
LuckyGiftWinningBannerViewModel *model = [LuckyGiftWinningBannerViewModel modelWithDictionary:attachment.data];
|
LuckyGiftWinningBannerViewModel *model = [LuckyGiftWinningBannerViewModel modelWithDictionary:attachment.data];
|
||||||
|
|
||||||
CGFloat width = kGetScaleWidth(346.5);
|
CGFloat width = kGetScaleWidth(kBannerWidth);
|
||||||
CGFloat height = kGetScaleWidth(82.5);
|
CGFloat height = kGetScaleWidth(kBannerHeight);
|
||||||
LuckyGiftWinningBannerView *bannerView = [[LuckyGiftWinningBannerView alloc] initWithFrame:CGRectMake(KScreenWidth, 80, width, height)];
|
CGRect frame = CGRectMake(KScreenWidth, kBannerTopMargin, width, height);
|
||||||
|
|
||||||
|
LuckyGiftWinningBannerView *bannerView = [[LuckyGiftWinningBannerView alloc] initWithFrame:frame];
|
||||||
bannerView.model = model;
|
bannerView.model = model;
|
||||||
bannerView.completeDisplay = complete;
|
bannerView.completeDisplay = complete;
|
||||||
bannerView.exitCurrentRoom = exit;
|
bannerView.exitCurrentRoom = exit;
|
||||||
bannerView.currentRoomUid = roomUid;
|
bannerView.currentRoomUid = roomUid;
|
||||||
[superView addSubview:bannerView];
|
[superView addSubview:bannerView];
|
||||||
|
|
||||||
@kWeakify(bannerView);
|
[bannerView animateDisplay];
|
||||||
[UIView animateWithDuration:0.25 animations:^{
|
}
|
||||||
bannerView.center = CGPointMake(superView.center.x, height/2 + 80);
|
|
||||||
|
- (void)animateDisplay {
|
||||||
|
@kWeakify(self);
|
||||||
|
[UIView animateWithDuration:kAnimationDuration animations:^{
|
||||||
|
@kStrongify(self);
|
||||||
|
self.center = CGPointMake(self.superview.center.x, self.frame.size.height/2 + kBannerTopMargin);
|
||||||
} completion:^(BOOL finished) {
|
} completion:^(BOOL finished) {
|
||||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
@kStrongify(self);
|
||||||
[UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kDisplayDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||||
bannerView.frame = CGRectMake(-KScreenWidth, 80, width, height);
|
[self animateDisappear];
|
||||||
} completion:^(BOOL finished) {
|
|
||||||
@kStrongify(bannerView);
|
|
||||||
[bannerView removeFromSuperview];
|
|
||||||
if (bannerView.completeDisplay) {
|
|
||||||
bannerView.completeDisplay();
|
|
||||||
}
|
|
||||||
}];
|
|
||||||
});
|
});
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (void)animateDisappear {
|
||||||
|
@kWeakify(self);
|
||||||
|
[UIView animateWithDuration:kAnimationDuration
|
||||||
|
delay:0
|
||||||
|
options:UIViewAnimationOptionCurveEaseInOut
|
||||||
|
animations:^{
|
||||||
|
@kStrongify(self);
|
||||||
|
self.frame = CGRectMake(-KScreenWidth, kBannerTopMargin, self.frame.size.width, self.frame.size.height);
|
||||||
|
} completion:^(BOOL finished) {
|
||||||
|
@kStrongify(self);
|
||||||
|
[self removeFromSuperview];
|
||||||
|
if (self.completeDisplay) {
|
||||||
|
self.completeDisplay();
|
||||||
|
}
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
- (void)setModel:(LuckyGiftWinningBannerViewModel *)model {
|
- (void)setModel:(LuckyGiftWinningBannerViewModel *)model {
|
||||||
_model = model;
|
_model = model;
|
||||||
self.avatarImage.imageUrl = model.avatar;
|
self.avatarImageView.imageUrl = model.avatar;
|
||||||
self.giftNameLabel.text = [model giftName];
|
self.giftNameLabel.text = [model giftName];
|
||||||
self.timesLabel.text = model.times;
|
self.timesLabel.text = model.times;
|
||||||
self.coinsLabel.text = [NSString formatNumberToKOrM:model.coins];
|
self.coinsLabel.text = [NSString formatNumberToKOrM:model.coins];
|
||||||
@@ -127,13 +156,13 @@ exitCurrentRoom:(void(^)(void))exit {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
__block NSString *targetRoomUid = self.model.roomUid;
|
|
||||||
@kWeakify(self);
|
@kWeakify(self);
|
||||||
[TTPopup alertWithMessage:YMLocalizedString(@"Combo_10") confirmHandler:^{
|
[TTPopup alertWithMessage:YMLocalizedString(@"Combo_10") confirmHandler:^{
|
||||||
@kStrongify(self);
|
@kStrongify(self);
|
||||||
if (self.exitCurrentRoom) {
|
if (self.exitCurrentRoom) {
|
||||||
self.exitCurrentRoom();
|
self.exitCurrentRoom();
|
||||||
}
|
}
|
||||||
|
NSString *targetRoomUid = self.model.roomUid;
|
||||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||||
[XPRoomViewController openRoom:targetRoomUid
|
[XPRoomViewController openRoom:targetRoomUid
|
||||||
viewController:[XCCurrentVCStackManager shareManager].getCurrentVC];
|
viewController:[XCCurrentVCStackManager shareManager].getCurrentVC];
|
||||||
@@ -153,8 +182,8 @@ exitCurrentRoom:(void(^)(void))exit {
|
|||||||
make.width.mas_equalTo(self.ballImageView.mas_height);
|
make.width.mas_equalTo(self.ballImageView.mas_height);
|
||||||
}];
|
}];
|
||||||
|
|
||||||
[self addSubview:self.avatarImage];
|
[self addSubview:self.avatarImageView];
|
||||||
[self.avatarImage mas_makeConstraints:^(MASConstraintMaker *make) {
|
[self.avatarImageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
make.leading.mas_equalTo(kGetScaleWidth(8));
|
make.leading.mas_equalTo(kGetScaleWidth(8));
|
||||||
make.top.mas_equalTo(kGetScaleWidth(24));
|
make.top.mas_equalTo(kGetScaleWidth(24));
|
||||||
make.width.height.mas_equalTo(kGetScaleWidth(43));
|
make.width.height.mas_equalTo(kGetScaleWidth(43));
|
||||||
@@ -163,8 +192,8 @@ exitCurrentRoom:(void(^)(void))exit {
|
|||||||
UILabel *titleLabel_1 = [UILabel labelInitWithText:YMLocalizedString(@"Combo_0") font:kFontSemibold(14) textColor:[UIColor whiteColor]];
|
UILabel *titleLabel_1 = [UILabel labelInitWithText:YMLocalizedString(@"Combo_0") font:kFontSemibold(14) textColor:[UIColor whiteColor]];
|
||||||
[self addSubview:titleLabel_1];
|
[self addSubview:titleLabel_1];
|
||||||
[titleLabel_1 mas_makeConstraints:^(MASConstraintMaker *make) {
|
[titleLabel_1 mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
make.top.mas_equalTo(self.avatarImage).offset(2);
|
make.top.mas_equalTo(self.avatarImageView).offset(2);
|
||||||
make.leading.mas_equalTo(self.avatarImage.mas_trailing).offset(10);
|
make.leading.mas_equalTo(self.avatarImageView.mas_trailing).offset(10);
|
||||||
}];
|
}];
|
||||||
|
|
||||||
[self addSubview:self.giftNameLabel];
|
[self addSubview:self.giftNameLabel];
|
||||||
@@ -176,8 +205,8 @@ exitCurrentRoom:(void(^)(void))exit {
|
|||||||
UILabel *titleLabel_2 = [UILabel labelInitWithText:YMLocalizedString(@"Combo_4") font:kFontSemibold(14) textColor:[UIColor whiteColor]];
|
UILabel *titleLabel_2 = [UILabel labelInitWithText:YMLocalizedString(@"Combo_4") font:kFontSemibold(14) textColor:[UIColor whiteColor]];
|
||||||
[self addSubview:titleLabel_2];
|
[self addSubview:titleLabel_2];
|
||||||
[titleLabel_2 mas_makeConstraints:^(MASConstraintMaker *make) {
|
[titleLabel_2 mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
make.bottom.mas_equalTo(self.avatarImage.mas_bottom).offset(-2);
|
make.bottom.mas_equalTo(self.avatarImageView.mas_bottom).offset(-2);
|
||||||
make.leading.mas_equalTo(self.avatarImage.mas_trailing).offset(10);
|
make.leading.mas_equalTo(self.avatarImageView.mas_trailing).offset(10);
|
||||||
}];
|
}];
|
||||||
|
|
||||||
[self addSubview:self.timesLabel];
|
[self addSubview:self.timesLabel];
|
||||||
@@ -226,19 +255,17 @@ exitCurrentRoom:(void(^)(void))exit {
|
|||||||
return _ballImageView;
|
return _ballImageView;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NetImageView *)avatarImage {
|
- (NetImageView *)avatarImageView {
|
||||||
if (!_avatarImage) {
|
if (!_avatarImageView) {
|
||||||
NetImageConfig * config = [[NetImageConfig alloc]init];
|
NetImageConfig * config = [[NetImageConfig alloc]init];
|
||||||
config.placeHolder = [UIImageConstant defaultAvatarPlaceholder];
|
config.placeHolder = [UIImageConstant defaultAvatarPlaceholder];
|
||||||
config.imageType = ImageTypeCornerAvatar;
|
config.imageType = ImageTypeCornerAvatar;
|
||||||
_avatarImage = [[NetImageView alloc] initWithConfig:config];
|
_avatarImageView = [[NetImageView alloc] initWithConfig:config];
|
||||||
_avatarImage.backgroundColor = [UIColor clearColor];
|
_avatarImageView.backgroundColor = [UIColor clearColor];
|
||||||
_avatarImage.contentMode = UIViewContentModeScaleAspectFill;
|
_avatarImageView.contentMode = UIViewContentModeScaleAspectFill;
|
||||||
_avatarImage.layer.cornerRadius = kGetScaleWidth(43/2);
|
[_avatarImageView setCornerRadius:kGetScaleWidth(43/2)];
|
||||||
_avatarImage.layer.masksToBounds = YES;
|
|
||||||
_avatarImage.clipsToBounds = YES;
|
|
||||||
}
|
}
|
||||||
return _avatarImage;
|
return _avatarImageView;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (UILabel *)giftNameLabel {
|
- (UILabel *)giftNameLabel {
|
||||||
|
@@ -115,14 +115,6 @@
|
|||||||
[stackView addArrangedSubview:self.coinIcon];
|
[stackView addArrangedSubview:self.coinIcon];
|
||||||
[stackView addArrangedSubview:self.winPriceLabel];
|
[stackView addArrangedSubview:self.winPriceLabel];
|
||||||
|
|
||||||
[self.coinIcon mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
||||||
make.size.mas_equalTo(CGSizeMake(21, 21));
|
|
||||||
}];
|
|
||||||
|
|
||||||
[self.winPriceLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
||||||
make.height.mas_equalTo(35);
|
|
||||||
}];
|
|
||||||
|
|
||||||
UIStackView *stackView_2 = [[UIStackView alloc] init];
|
UIStackView *stackView_2 = [[UIStackView alloc] init];
|
||||||
stackView_2.spacing = 4;
|
stackView_2.spacing = 4;
|
||||||
[self addSubview:stackView_2];
|
[self addSubview:stackView_2];
|
||||||
@@ -149,10 +141,6 @@
|
|||||||
[[NSNotificationCenter defaultCenter] postNotificationName:@"receiveLuckGiftWinning" object:model.coins];
|
[[NSNotificationCenter defaultCenter] postNotificationName:@"receiveLuckGiftWinning" object:model.coins];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)display {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
- (UIImageView *)coinIcon {
|
- (UIImageView *)coinIcon {
|
||||||
if (!_coinIcon) {
|
if (!_coinIcon) {
|
||||||
|
@@ -79,6 +79,9 @@
|
|||||||
#import "GameUniversalBannerView.h"
|
#import "GameUniversalBannerView.h"
|
||||||
#import "RoomHighValueGiftBannerAnimation.h"
|
#import "RoomHighValueGiftBannerAnimation.h"
|
||||||
|
|
||||||
|
#import "GiftAnimationHelper.h"
|
||||||
|
#import "GiftAnimationManager.h"
|
||||||
|
|
||||||
@interface XPRoomAnimationView ()<
|
@interface XPRoomAnimationView ()<
|
||||||
SVGAPlayerDelegate,
|
SVGAPlayerDelegate,
|
||||||
NIMBroadcastManagerDelegate,
|
NIMBroadcastManagerDelegate,
|
||||||
@@ -90,7 +93,9 @@ XPRoomStarKitchenBannerViewDelegate,
|
|||||||
PAGViewListener,
|
PAGViewListener,
|
||||||
XPRoomAnchorRankBannerViewDelegate,
|
XPRoomAnchorRankBannerViewDelegate,
|
||||||
PIRoomGiftBroadcastWindowDelegate,
|
PIRoomGiftBroadcastWindowDelegate,
|
||||||
PIUniversalBannerViewDelegate>
|
PIUniversalBannerViewDelegate,
|
||||||
|
GiftAnimationDelegate>
|
||||||
|
|
||||||
///展示的不同层级
|
///展示的不同层级
|
||||||
///最底层的
|
///最底层的
|
||||||
@property (nonatomic,strong) XPRoomAnimationHitView * lowLevelView;
|
@property (nonatomic,strong) XPRoomAnimationHitView * lowLevelView;
|
||||||
@@ -116,24 +121,17 @@ PIUniversalBannerViewDelegate>
|
|||||||
///代理
|
///代理
|
||||||
@property (nonatomic,weak) id<RoomHostDelegate>delegate;
|
@property (nonatomic,weak) id<RoomHostDelegate>delegate;
|
||||||
|
|
||||||
///复用池
|
|
||||||
@property (strong,nonatomic)NSMutableSet * bannerDequePool;
|
|
||||||
///可见池
|
|
||||||
@property (strong,nonatomic)NSMutableSet * bannerVisiablePool;
|
|
||||||
///礼物定时器 6s刷新一次
|
///礼物定时器 6s刷新一次
|
||||||
@property (nonatomic,strong)dispatch_source_t giftEffectTimer;
|
@property (nonatomic,strong)dispatch_source_t giftEffectTimer;
|
||||||
|
|
||||||
|
|
||||||
#pragma mark - 送礼物的动画的
|
#pragma mark - 送礼物的动画的
|
||||||
///礼物的队列
|
///礼物的队列
|
||||||
@property (nonatomic,strong) NSMutableArray<GiftReceiveInfoModel *> *giftQueue;
|
//@property (nonatomic,strong) NSMutableArray<GiftReceiveInfoModel *> *giftQueue;
|
||||||
///定时器
|
/////定时器
|
||||||
@property (nonatomic ,strong)dispatch_source_t giftTimer;
|
//@property (nonatomic ,strong)dispatch_source_t giftTimer;
|
||||||
///复用池 应为送礼物的动画是一个很频繁的事情 所以可以减少内存的消耗
|
@property(nonatomic, strong) GiftAnimationHelper *giftAnimationHelper;
|
||||||
@property (nonatomic,strong) NSMutableSet<NetImageView *> * giftReuseArray;
|
@property(nonatomic, strong) GiftAnimationManager *giftAnimationManager;
|
||||||
///可见池
|
|
||||||
@property (nonatomic,strong) NSMutableSet<NetImageView *> * giftVisibleArray;
|
|
||||||
|
|
||||||
///大礼物是否正在播放
|
///大礼物是否正在播放
|
||||||
@property (nonatomic,assign) BOOL isLargeGiftAnimating;
|
@property (nonatomic,assign) BOOL isLargeGiftAnimating;
|
||||||
#pragma mark - 进房座驾动画的
|
#pragma mark - 进房座驾动画的
|
||||||
@@ -205,10 +203,10 @@ PIUniversalBannerViewDelegate>
|
|||||||
self.giftEffectTimer = nil;
|
self.giftEffectTimer = nil;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(self.giftTimer != nil){
|
// if(self.giftTimer != nil){
|
||||||
dispatch_source_cancel(self.giftTimer);
|
// dispatch_source_cancel(self.giftTimer);
|
||||||
self.giftTimer = nil;
|
// self.giftTimer = nil;
|
||||||
}
|
// }
|
||||||
[self.giftPagView removeListener:self];
|
[self.giftPagView removeListener:self];
|
||||||
}
|
}
|
||||||
- (instancetype)initWithDelegate:(id<RoomHostDelegate>)delegate {
|
- (instancetype)initWithDelegate:(id<RoomHostDelegate>)delegate {
|
||||||
@@ -216,9 +214,14 @@ PIUniversalBannerViewDelegate>
|
|||||||
if (self) {
|
if (self) {
|
||||||
[[NIMSDK sharedSDK].broadcastManager addDelegate:self];
|
[[NIMSDK sharedSDK].broadcastManager addDelegate:self];
|
||||||
self.delegate = delegate;
|
self.delegate = delegate;
|
||||||
|
|
||||||
[self initSubViews];
|
[self initSubViews];
|
||||||
[self initSubViewConstraints];
|
[self initSubViewConstraints];
|
||||||
|
|
||||||
|
self.giftAnimationHelper = [[GiftAnimationHelper alloc] init];
|
||||||
|
self.giftAnimationManager = [[GiftAnimationManager alloc] initWithContainerView:self.lowLevelView];
|
||||||
|
self.giftAnimationManager.delegate = self;
|
||||||
|
|
||||||
_roomEffectModelsQueueV2 = [NSMutableArray array];
|
_roomEffectModelsQueueV2 = [NSMutableArray array];
|
||||||
_GiftDynamicEffectListPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) xpSafeObjectAtIndex:0] stringByAppendingPathComponent:@"GiftDynamicEffectList"];
|
_GiftDynamicEffectListPath = [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) xpSafeObjectAtIndex:0] stringByAppendingPathComponent:@"GiftDynamicEffectList"];
|
||||||
|
|
||||||
@@ -336,7 +339,11 @@ PIUniversalBannerViewDelegate>
|
|||||||
receiveInfo.isBatch = (attachment.second == Custom_Message_Sub_AllBatchSend || attachment.second == Custom_Message_Sub_AllBatchMicroLuckySend);
|
receiveInfo.isBatch = (attachment.second == Custom_Message_Sub_AllBatchSend || attachment.second == Custom_Message_Sub_AllBatchMicroLuckySend);
|
||||||
receiveInfo.isComboBatch = attachment.second == Custom_Message_Sub_AllMicroSend;
|
receiveInfo.isComboBatch = attachment.second == Custom_Message_Sub_AllMicroSend;
|
||||||
|
|
||||||
[self receiveGiftHandleSendGiftAnimation:attachment];
|
if (receiveInfo.gift.notifyFull && attachment.second == Custom_Message_Sub_Gift_Send) {
|
||||||
|
// return;
|
||||||
|
} else {
|
||||||
|
[self receiveGiftHandleSendGiftAnimation:attachment];
|
||||||
|
}
|
||||||
|
|
||||||
if (receiveInfo.isLuckyBagGift) {
|
if (receiveInfo.isLuckyBagGift) {
|
||||||
if (!self.delegate.getRoomInfo.hasAnimationEffect) {return;}
|
if (!self.delegate.getRoomInfo.hasAnimationEffect) {return;}
|
||||||
@@ -1662,10 +1669,11 @@ PIUniversalBannerViewDelegate>
|
|||||||
///在最外面判断是否可以拿到那个礼物 后面使用就不用判断了
|
///在最外面判断是否可以拿到那个礼物 后面使用就不用判断了
|
||||||
receiveInfo.gift = giftInfo;
|
receiveInfo.gift = giftInfo;
|
||||||
receiveInfo.isLuckyBagGift = (attachment.second == Custom_Message_Sub_AllMicroLuckySend || attachment.second == Custom_Message_Sub_AllBatchMicroLuckySend || attachment.second == Custom_Message_Sub_Gift_LuckySend);
|
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];
|
[self.giftAnimationManager enqueueGift:receiveInfo];
|
||||||
if (self.giftTimer == nil && self.giftQueue > 0) {
|
// [self.giftQueue addObject:receiveInfo];
|
||||||
[self startGiftQueueTimer];
|
// if (self.giftTimer == nil && self.giftQueue > 0) {
|
||||||
}
|
// [self startGiftQueueTimer];
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark - 收到礼物展示动画
|
#pragma mark - 收到礼物展示动画
|
||||||
@@ -1693,260 +1701,38 @@ PIUniversalBannerViewDelegate>
|
|||||||
///在最外面判断是否可以拿到那个礼物 后面使用就不用判断了
|
///在最外面判断是否可以拿到那个礼物 后面使用就不用判断了
|
||||||
receiveInfo.gift = giftInfo;
|
receiveInfo.gift = giftInfo;
|
||||||
receiveInfo.isLuckyBagGift = (attachment.second == Custom_Message_Sub_AllMicroLuckySend || attachment.second == Custom_Message_Sub_AllBatchMicroLuckySend || attachment.second == Custom_Message_Sub_Gift_LuckySend);
|
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];
|
[self.giftAnimationManager enqueueGift:receiveInfo];
|
||||||
if (self.giftTimer == nil && self.giftQueue > 0) {
|
// [self.giftQueue addObject:receiveInfo];
|
||||||
[self startGiftQueueTimer];
|
// if (self.giftTimer == nil && self.giftQueue > 0) {
|
||||||
}
|
// [self startGiftQueueTimer];
|
||||||
|
// }
|
||||||
}
|
}
|
||||||
|
|
||||||
//扫描礼物队列
|
//扫描礼物队列
|
||||||
- (void)startGiftQueueTimer {
|
//- (void)startGiftQueueTimer {
|
||||||
NSTimeInterval period = 0.5; //设置时间间隔一个礼物动画的时间
|
// static 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_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_timer(_timer, DISPATCH_TIME_NOW, period * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
|
||||||
dispatch_source_set_event_handler(_timer, ^{
|
// dispatch_source_set_event_handler(_timer, ^{
|
||||||
dispatch_async(dispatch_get_main_queue(), ^{
|
// dispatch_async(dispatch_get_main_queue(), ^{
|
||||||
if (self.giftQueue.count) {
|
// if (self.giftQueue.count) {
|
||||||
GiftReceiveInfoModel * receiveInfo = self.giftQueue.firstObject;
|
// GiftReceiveInfoModel * receiveInfo = self.giftQueue.firstObject;
|
||||||
[self handoutGiftDistributeAnimation:receiveInfo];
|
//// [self handoutGiftDistributeAnimation:receiveInfo];
|
||||||
[self.giftQueue removeObject:receiveInfo];
|
// [self.giftAnimationManager enqueueGift:receiveInfo];
|
||||||
}else {
|
// [self.giftQueue removeObject:receiveInfo];
|
||||||
dispatch_source_cancel(_timer);
|
// }else {
|
||||||
self.giftTimer = nil;
|
// dispatch_source_cancel(_timer);
|
||||||
}
|
// self.giftTimer = nil;
|
||||||
});
|
// }
|
||||||
});
|
// });
|
||||||
dispatch_resume(_timer);
|
// });
|
||||||
self.giftTimer = _timer;
|
// dispatch_resume(_timer);
|
||||||
}
|
// self.giftTimer = _timer;
|
||||||
|
//}
|
||||||
|
|
||||||
///处理礼物的分发动画
|
#pragma mark - GiftAnimationManagerDelegate
|
||||||
- (void)handoutGiftDistributeAnimation:(GiftReceiveInfoModel *)receiveInfo {
|
- (CGPoint)animationPointAtStageViewByUid:(NSString *)uid {
|
||||||
GiftInfoModel * giftInfo = receiveInfo.gift;
|
return [self.delegate animationPointAtStageViewByUid:uid];
|
||||||
NSString * sendUid = receiveInfo.uid;
|
|
||||||
CGPoint starPoint = [self getGiftAnimationPoint:sendUid isEnd:NO];
|
|
||||||
CGPoint endPoint;
|
|
||||||
NSArray * targetUids;
|
|
||||||
if (receiveInfo.isLuckyBagGift) {
|
|
||||||
targetUids = @[receiveInfo.targetUid];
|
|
||||||
} else {
|
|
||||||
targetUids = receiveInfo.targetUids;
|
|
||||||
if (targetUids.count <= 0) {
|
|
||||||
if (receiveInfo.targetUsers) {
|
|
||||||
targetUids = [receiveInfo.targetUsers valueForKeyPath:@"uid"];
|
|
||||||
}
|
|
||||||
if (targetUids.count <=0) {
|
|
||||||
targetUids = [NSString isEmpty:receiveInfo.targetUid] ? @[] : @[receiveInfo.targetUid];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#if DEBUG
|
|
||||||
for (NSInteger i=0;i<15;i++) {
|
|
||||||
endPoint = [self.delegate animationPointAtStageViewByIndex:i];
|
|
||||||
BOOL isCombing = [[GiftComboManager sharedManager] isGiftCombing] && [sendUid isEqualToString:[AccountInfoStorage instance].getUid];
|
|
||||||
CGFloat time = isCombing ? 0.25 : 0.5;
|
|
||||||
dispatch_time_t timer = dispatch_time(DISPATCH_TIME_NOW, time * NSEC_PER_SEC);
|
|
||||||
dispatch_after(timer, dispatch_get_main_queue(), ^{
|
|
||||||
[self beginGiftAnimation:giftInfo.giftUrl
|
|
||||||
startPoint:starPoint
|
|
||||||
endPoint:endPoint
|
|
||||||
isGiftCombing:isCombing];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
for (NSString *targetUid in targetUids) {
|
|
||||||
NSString * userId = targetUid;
|
|
||||||
if ([userId isKindOfClass:[NSNumber class]]) {
|
|
||||||
userId = ((NSNumber *)userId).stringValue;
|
|
||||||
}
|
|
||||||
endPoint = [self getGiftAnimationPoint:userId isEnd:YES];
|
|
||||||
dispatch_time_t timer = dispatch_time(DISPATCH_TIME_NOW, 0.5 * NSEC_PER_SEC);
|
|
||||||
|
|
||||||
BOOL isCombing = [[GiftComboManager sharedManager] isGiftCombing] && [sendUid isEqualToString:[AccountInfoStorage instance].getUid];
|
|
||||||
|
|
||||||
if (isCombing) {
|
|
||||||
timer = dispatch_time(DISPATCH_TIME_NOW, 0.25 * NSEC_PER_SEC);
|
|
||||||
}
|
|
||||||
dispatch_after(timer, dispatch_get_main_queue(), ^{
|
|
||||||
[self beginGiftAnimation:giftInfo.giftUrl
|
|
||||||
startPoint:starPoint
|
|
||||||
endPoint:endPoint
|
|
||||||
isGiftCombing:isCombing];
|
|
||||||
});
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
///起点
|
|
||||||
- (CGPoint)getGiftAnimationPoint:(NSString *)uid isEnd:(BOOL)isEnd{
|
|
||||||
CGPoint point = [self.delegate animationPointAtStageViewByUid:uid];
|
|
||||||
//没有找到那个点 那个用户不再坑位上
|
|
||||||
if (point.x <= 0 || point.y <= 0) {
|
|
||||||
if (isEnd) {
|
|
||||||
point = CGPointMake([UIScreen mainScreen].bounds.size.width /2 + 30, 44 + kSafeAreaTopHeight);
|
|
||||||
} else {
|
|
||||||
point = CGPointMake([UIScreen mainScreen].bounds.size.width / 2, 44 + kSafeAreaTopHeight);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ([[GiftComboManager sharedManager] isGiftCombing] &&
|
|
||||||
[uid isEqualToString:[AccountInfoStorage instance].getUid] &&
|
|
||||||
isEnd == false) {
|
|
||||||
if (isMSRTL()) {
|
|
||||||
point = CGPointMake(kGetScaleWidth(86), [UIScreen mainScreen].bounds.size.height - kSafeAreaTopHeight - kGetScaleWidth(140));
|
|
||||||
} else {
|
|
||||||
if (KScreenWidth <= 375) {
|
|
||||||
point = CGPointMake(kGetScaleWidth([UIScreen mainScreen].bounds.size.width - kGetScaleWidth(86)), [UIScreen mainScreen].bounds.size.height - kSafeAreaBottomHeight - kGetScaleWidth(140));
|
|
||||||
} else {
|
|
||||||
point = CGPointMake(kGetScaleWidth([UIScreen mainScreen].bounds.size.width - kGetScaleWidth(150)), [UIScreen mainScreen].bounds.size.height - kSafeAreaBottomHeight - kGetScaleWidth(140));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return point;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)beginGiftAnimation:(NSString *)giftUrl
|
|
||||||
startPoint:(CGPoint)startPoint
|
|
||||||
endPoint:(CGPoint)endPoint
|
|
||||||
isGiftCombing:(BOOL)isGiftCombing {
|
|
||||||
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];
|
|
||||||
|
|
||||||
CGFloat delay = 3.2;
|
|
||||||
CAAnimationGroup *group = [self createGiftAnimationStartPoint:startPoint endPoint:endPoint];
|
|
||||||
if (isGiftCombing) {
|
|
||||||
delay = 1.0;
|
|
||||||
group = [self createGiftComboAnimationStartPoint:startPoint endPoint:endPoint];
|
|
||||||
}
|
|
||||||
// 确保视图在动画开始前设置到 startPoint 位置
|
|
||||||
giftImageView.layer.position = startPoint;
|
|
||||||
[giftImageView.layer addAnimation:group forKey:@"giftDisplayViewAnimation"];
|
|
||||||
[self performSelector:@selector(aniationDidFinish:) withObject:giftImageView afterDelay:(delay+0.25)];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (CAAnimationGroup *)createGiftComboAnimationStartPoint:(CGPoint)startPoint
|
|
||||||
endPoint:(CGPoint)endPoint {
|
|
||||||
// 缩放动画1: 动画开始时缩放至 0.4
|
|
||||||
CAKeyframeAnimation *scaleAnimation1 = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"];
|
|
||||||
scaleAnimation1.duration = 0.1;
|
|
||||||
scaleAnimation1.values = @[@1.0, @0.4];
|
|
||||||
scaleAnimation1.repeatCount = 1;
|
|
||||||
scaleAnimation1.calculationMode = kCAAnimationCubic;
|
|
||||||
scaleAnimation1.removedOnCompletion = NO;
|
|
||||||
scaleAnimation1.fillMode = kCAFillModeForwards;
|
|
||||||
|
|
||||||
// 位移动画: 0.5秒内从起点移动到目标点
|
|
||||||
CAKeyframeAnimation *positionAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
|
|
||||||
positionAnimation.duration = 0.5;
|
|
||||||
positionAnimation.beginTime = 0.1; // 缩放结束后开始位移
|
|
||||||
positionAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseInEaseOut];
|
|
||||||
positionAnimation.values = @[[NSValue valueWithCGPoint:startPoint], [NSValue valueWithCGPoint:endPoint]];
|
|
||||||
positionAnimation.repeatCount = 1;
|
|
||||||
positionAnimation.removedOnCompletion = NO;
|
|
||||||
positionAnimation.fillMode = kCAFillModeForwards;
|
|
||||||
|
|
||||||
// 缩放动画2: 在位移的过程中逐渐变大到 1.2
|
|
||||||
CAKeyframeAnimation *scaleAnimation2 = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"];
|
|
||||||
scaleAnimation2.duration = 0.5;
|
|
||||||
scaleAnimation2.beginTime = 0.1; // 同时与位移动画进行
|
|
||||||
scaleAnimation2.values = @[@0.4, @2];
|
|
||||||
scaleAnimation2.repeatCount = 1;
|
|
||||||
scaleAnimation2.calculationMode = kCAAnimationCubic;
|
|
||||||
scaleAnimation2.removedOnCompletion = NO;
|
|
||||||
scaleAnimation2.fillMode = kCAFillModeForwards;
|
|
||||||
|
|
||||||
// 创建动画组
|
|
||||||
CAAnimationGroup *group = [CAAnimationGroup animation];
|
|
||||||
group.duration = 0.6; // 总时间为 0.1 (缩放) + 0.5 (位移与缩放)
|
|
||||||
group.animations = @[scaleAnimation1, positionAnimation, scaleAnimation2];
|
|
||||||
group.repeatCount = 1;
|
|
||||||
group.removedOnCompletion = NO;
|
|
||||||
group.fillMode = kCAFillModeForwards;
|
|
||||||
|
|
||||||
return group;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// 图片运动的动画组
|
|
||||||
/// @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 - 全服礼物 飘屏
|
#pragma mark - 全服礼物 飘屏
|
||||||
@@ -1957,7 +1743,9 @@ PIUniversalBannerViewDelegate>
|
|||||||
if (giftNotifyInfo.ceremonyGift)return;
|
if (giftNotifyInfo.ceremonyGift)return;
|
||||||
// if(giftNotifyInfo.isHomeShow == YES)return; ///房间外飘屏 在tabbar中监听
|
// if(giftNotifyInfo.isHomeShow == YES)return; ///房间外飘屏 在tabbar中监听
|
||||||
// if(giftNotifyInfo.roomUid == self.delegate.getRoomInfo.uid)return; ///自己的房间跨房间飘屏不用走
|
// if(giftNotifyInfo.roomUid == self.delegate.getRoomInfo.uid)return; ///自己的房间跨房间飘屏不用走
|
||||||
if (self.animationListA.count == 0 && self.isPlayOfB == NO && self.isPlayOfA == NO) {
|
if (self.animationListA.count == 0 &&
|
||||||
|
self.isPlayOfB == NO &&
|
||||||
|
self.isPlayOfA == NO) {
|
||||||
[self createGiftBroadcastViewAnimation:giftNotifyInfo];
|
[self createGiftBroadcastViewAnimation:giftNotifyInfo];
|
||||||
}
|
}
|
||||||
[self.animationListA addObject:giftNotifyInfo];
|
[self.animationListA addObject:giftNotifyInfo];
|
||||||
@@ -2057,8 +1845,6 @@ PIUniversalBannerViewDelegate>
|
|||||||
[self.animationListB addObject:prizeModel];
|
[self.animationListB addObject:prizeModel];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
- (void)createBigPrizeAnimation:(PIBaseAnimationViewModel *)prizeModel {
|
- (void)createBigPrizeAnimation:(PIBaseAnimationViewModel *)prizeModel {
|
||||||
|
|
||||||
self.isPlayOfB = YES;
|
self.isPlayOfB = YES;
|
||||||
@@ -2094,11 +1880,6 @@ PIUniversalBannerViewDelegate>
|
|||||||
[self.animationListB removeObjectAtIndex:0];
|
[self.animationListB removeObjectAtIndex:0];
|
||||||
}
|
}
|
||||||
self.isPlayOfB = NO;
|
self.isPlayOfB = NO;
|
||||||
// if(self.isAnimationListAFinish == YES){
|
|
||||||
// self.isAnimationListAFinish = NO;
|
|
||||||
// [self playAnimationWithModel];
|
|
||||||
// return;
|
|
||||||
// }
|
|
||||||
[self playAnimationWithModel];
|
[self playAnimationWithModel];
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
@@ -3070,19 +2851,6 @@ PIUniversalBannerViewDelegate>
|
|||||||
return _parser;
|
return _parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSMutableSet *)bannerDequePool {
|
|
||||||
if (!_bannerDequePool) {
|
|
||||||
_bannerDequePool = [NSMutableSet set];
|
|
||||||
}
|
|
||||||
return _bannerDequePool;
|
|
||||||
}
|
|
||||||
- (NSMutableSet *)bannerVisiablePool {
|
|
||||||
if (!_bannerVisiablePool) {
|
|
||||||
_bannerVisiablePool = [NSMutableSet set];
|
|
||||||
}
|
|
||||||
return _bannerVisiablePool;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (XPRoomAnimationHitView *)lowLevelView {
|
- (XPRoomAnimationHitView *)lowLevelView {
|
||||||
if (!_lowLevelView) {
|
if (!_lowLevelView) {
|
||||||
_lowLevelView = [[XPRoomAnimationHitView alloc] init];
|
_lowLevelView = [[XPRoomAnimationHitView alloc] init];
|
||||||
@@ -3110,26 +2878,12 @@ PIUniversalBannerViewDelegate>
|
|||||||
return _highLevleView;
|
return _highLevleView;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSMutableArray<GiftReceiveInfoModel *> *)giftQueue {
|
//- (NSMutableArray<GiftReceiveInfoModel *> *)giftQueue {
|
||||||
if (!_giftQueue) {
|
// if (!_giftQueue) {
|
||||||
_giftQueue = [NSMutableArray array];
|
// _giftQueue = [NSMutableArray array];
|
||||||
}
|
// }
|
||||||
return _giftQueue;
|
// return _giftQueue;
|
||||||
}
|
//}
|
||||||
|
|
||||||
- (NSMutableSet<NetImageView *> *)giftReuseArray {
|
|
||||||
if (!_giftReuseArray) {
|
|
||||||
_giftReuseArray = [NSMutableSet set];
|
|
||||||
}
|
|
||||||
return _giftReuseArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSMutableSet<NetImageView *> *)giftVisibleArray {
|
|
||||||
if (!_giftVisibleArray) {
|
|
||||||
_giftVisibleArray = [NSMutableSet set];
|
|
||||||
}
|
|
||||||
return _giftVisibleArray;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (NSMutableArray<NSDictionary *> *)carEffectQueue {
|
- (NSMutableArray<NSDictionary *> *)carEffectQueue {
|
||||||
if (_carEffectQueue == nil) {
|
if (_carEffectQueue == nil) {
|
||||||
|
@@ -55,30 +55,64 @@
|
|||||||
|
|
||||||
#pragma mark - 更新 UI
|
#pragma mark - 更新 UI
|
||||||
- (void)updateUIWithModel:(GiftReceiveInfoModel *)model {
|
- (void)updateUIWithModel:(GiftReceiveInfoModel *)model {
|
||||||
if ([NSString isEmpty:self.cacheIcon]) {
|
// 更新礼物图标
|
||||||
self.cacheIcon = model.gift.giftUrl;
|
@kWeakify(self);
|
||||||
} else {
|
[self updateCacheForProperty:self.cacheIcon newValue:model.gift.giftUrl updateBlock:^(NSString *value) {
|
||||||
if ([self.cacheIcon isEqualToString:model.gift.giftUrl]) {
|
@kStrongify(self);
|
||||||
self.cacheIcon = model.gift.giftUrl;
|
self.giftIcon.imageUrl = value;
|
||||||
self.giftIcon.imageUrl = model.gift.giftUrl;
|
}];
|
||||||
}
|
|
||||||
}
|
// 更新头像
|
||||||
if ([NSString isEmpty:self.cacheAvatar]) {
|
[self updateCacheForProperty:self.cacheAvatar newValue:model.avatar updateBlock:^(NSString *value) {
|
||||||
self.cacheIcon = model.avatar;
|
@kStrongify(self);
|
||||||
self.giftGiverAvatar.imageUrl = model.avatar;
|
self.giftGiverAvatar.imageUrl = value;
|
||||||
} else {
|
}];
|
||||||
if (![self.cacheAvatar isEqualToString:model.avatar]) {
|
|
||||||
self.cacheIcon = model.avatar;
|
// 更新名字
|
||||||
self.giftGiverAvatar.imageUrl = model.avatar;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
self.giftGiverNameLabel.text = model.nick;
|
self.giftGiverNameLabel.text = model.nick;
|
||||||
|
|
||||||
|
// 更新接收者名称
|
||||||
self.giftReceiverNameLabel.text = [self receiverNameForModel:model];
|
self.giftReceiverNameLabel.text = [self receiverNameForModel:model];
|
||||||
|
|
||||||
|
// 更新礼物计数
|
||||||
NSInteger total = model.comboCount * model.giftNum * model.receiveUserCount;
|
NSInteger total = model.comboCount * model.giftNum * model.receiveUserCount;
|
||||||
NSString *countStr = [NSString stringWithFormat:@"x%ld", (long)total];
|
NSString *countStr = [NSString stringWithFormat:@"x%ld", (long)total];
|
||||||
self.giftCountLabel.attributedText = [self generateAttributedStringForCount:countStr];
|
self.giftCountLabel.attributedText = [self generateAttributedStringForCount:countStr];
|
||||||
|
|
||||||
|
// if ([NSString isEmpty:self.cacheIcon]) {
|
||||||
|
// self.cacheIcon = model.gift.giftUrl;
|
||||||
|
// } else {
|
||||||
|
// if (![self.cacheIcon isEqualToString:model.gift.giftUrl]) {
|
||||||
|
// self.cacheIcon = model.gift.giftUrl;
|
||||||
|
// self.giftIcon.imageUrl = model.gift.giftUrl;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// if ([NSString isEmpty:self.cacheAvatar]) {
|
||||||
|
// self.cacheAvatar = model.avatar;
|
||||||
|
// self.giftGiverAvatar.imageUrl = model.avatar;
|
||||||
|
// } else {
|
||||||
|
// if (![self.cacheAvatar isEqualToString:model.avatar]) {
|
||||||
|
// self.cacheIcon = model.avatar;
|
||||||
|
// self.giftGiverAvatar.imageUrl = model.avatar;
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// self.giftGiverNameLabel.text = model.nick;
|
||||||
|
//
|
||||||
|
// self.giftReceiverNameLabel.text = [self receiverNameForModel:model];
|
||||||
|
//
|
||||||
|
// NSInteger total = model.comboCount * model.giftNum * model.receiveUserCount;
|
||||||
|
// NSString *countStr = [NSString stringWithFormat:@"x%ld", (long)total];
|
||||||
|
// self.giftCountLabel.attributedText = [self generateAttributedStringForCount:countStr];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)updateCacheForProperty:(NSString *)cacheProperty newValue:(NSString *)newValue updateBlock:(void (^)(NSString *value))updateBlock {
|
||||||
|
if ([NSString isEmpty:cacheProperty]) {
|
||||||
|
cacheProperty = newValue;
|
||||||
|
updateBlock(newValue);
|
||||||
|
} else if (![newValue isEqualToString:cacheProperty]) {
|
||||||
|
cacheProperty = newValue;
|
||||||
|
updateBlock(newValue);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSMutableAttributedString *)generateAttributedStringForCount:(NSString *)countStr {
|
- (NSMutableAttributedString *)generateAttributedStringForCount:(NSString *)countStr {
|
||||||
@@ -190,7 +224,9 @@
|
|||||||
|
|
||||||
[self addSubview:self.giftIcon];
|
[self addSubview:self.giftIcon];
|
||||||
[self.giftIcon mas_makeConstraints:^(MASConstraintMaker *make) {
|
[self.giftIcon mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
make.leading.mas_equalTo(self.giftReceiverNameLabel.mas_trailing).offset(8);
|
// make.leading.mas_equalTo(self.giftGiverNameLabel.mas_trailing).offset(8);
|
||||||
|
make.leading.greaterThanOrEqualTo(self.giftGiverNameLabel.mas_trailing).offset(8);
|
||||||
|
make.leading.greaterThanOrEqualTo(self.giftReceiverNameLabel.mas_trailing).offset(8);
|
||||||
make.bottom.mas_equalTo(self.backgroundImageView);
|
make.bottom.mas_equalTo(self.backgroundImageView);
|
||||||
make.size.mas_equalTo(CGSizeMake(kGetScaleWidth(48), kGetScaleWidth(48)));
|
make.size.mas_equalTo(CGSizeMake(kGetScaleWidth(48), kGetScaleWidth(48)));
|
||||||
}];
|
}];
|
||||||
|
@@ -18,6 +18,7 @@
|
|||||||
@property (nonatomic, strong) UILabel *comboCountLabel;
|
@property (nonatomic, strong) UILabel *comboCountLabel;
|
||||||
@property(nonatomic, strong) UILabel *comboGoldLabel;
|
@property(nonatomic, strong) UILabel *comboGoldLabel;
|
||||||
@property(nonatomic, strong) UILabel *updateGoldLabel;
|
@property(nonatomic, strong) UILabel *updateGoldLabel;
|
||||||
|
@property(nonatomic, strong) UILabel *winPriceGoldLabel;
|
||||||
@property (nonatomic, strong) SVGAImageView *playImageView;
|
@property (nonatomic, strong) SVGAImageView *playImageView;
|
||||||
@property (nonatomic, strong) SVGAVideoEntity *svgaVideoEntity;
|
@property (nonatomic, strong) SVGAVideoEntity *svgaVideoEntity;
|
||||||
@property (nonatomic, strong) CountdownRingView *countdownRingView;
|
@property (nonatomic, strong) CountdownRingView *countdownRingView;
|
||||||
@@ -25,6 +26,8 @@
|
|||||||
@property(nonatomic, strong) NSMutableArray *updateGoldQueue;
|
@property(nonatomic, strong) NSMutableArray *updateGoldQueue;
|
||||||
@property(nonatomic, assign) BOOL isAnimatingUpdateGold;
|
@property(nonatomic, assign) BOOL isAnimatingUpdateGold;
|
||||||
|
|
||||||
|
@property(nonatomic, strong) UIImpactFeedbackGenerator *f;
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@implementation GiftComboView
|
@implementation GiftComboView
|
||||||
@@ -39,6 +42,7 @@
|
|||||||
|
|
||||||
- (instancetype)init {
|
- (instancetype)init {
|
||||||
if (self = [super init]) {
|
if (self = [super init]) {
|
||||||
|
self.f = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleHeavy];
|
||||||
self.updateGoldQueue = @[].mutableCopy;
|
self.updateGoldQueue = @[].mutableCopy;
|
||||||
[self setupNotification];
|
[self setupNotification];
|
||||||
|
|
||||||
@@ -91,10 +95,6 @@
|
|||||||
double price = [[dic objectForKey:@"Price"] doubleValue];
|
double price = [[dic objectForKey:@"Price"] doubleValue];
|
||||||
BOOL isFromWinning = [[dic objectForKey:@"isFromWinning"] boolValue];
|
BOOL isFromWinning = [[dic objectForKey:@"isFromWinning"] boolValue];
|
||||||
[self updateCurrentGold:coin giftPrice:price isFromWinning:isFromWinning];
|
[self updateCurrentGold:coin giftPrice:price isFromWinning:isFromWinning];
|
||||||
// [[NSNotificationCenter defaultCenter] postNotificationName:@"receiveLuckGiftWinning"
|
|
||||||
// object:@{@"CurrentGold": receive.userPurse.diamonds,
|
|
||||||
// @"Price": @(receive.gift.goldPrice),
|
|
||||||
// @"isFromWinning":@(NO)}];
|
|
||||||
}
|
}
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
@@ -175,8 +175,14 @@
|
|||||||
|
|
||||||
[self addSubview:self.updateGoldLabel];
|
[self addSubview:self.updateGoldLabel];
|
||||||
[self.updateGoldLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
[self.updateGoldLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
make.centerX.mas_equalTo(bg);
|
make.trailing.mas_equalTo(self.comboGoldLabel);
|
||||||
make.bottom.mas_equalTo(self.comboGoldLabel.mas_bottom).offset(0);
|
make.bottom.mas_equalTo(self.comboGoldLabel);
|
||||||
|
}];
|
||||||
|
|
||||||
|
[self addSubview:self.winPriceGoldLabel];
|
||||||
|
[self.winPriceGoldLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.trailing.mas_equalTo(self.comboGoldLabel);
|
||||||
|
make.bottom.mas_equalTo(self.comboGoldLabel);
|
||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -207,7 +213,9 @@
|
|||||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||||
@kStrongify(self);
|
@kStrongify(self);
|
||||||
// 1521 连续震动 3 次
|
// 1521 连续震动 3 次
|
||||||
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
|
// AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
|
||||||
|
// AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate));
|
||||||
|
[self.f impactOccurred];
|
||||||
|
|
||||||
[[GiftComboManager sharedManager] sendGift];
|
[[GiftComboManager sharedManager] sendGift];
|
||||||
[self.playImageView startAnimation];
|
[self.playImageView startAnimation];
|
||||||
@@ -231,39 +239,111 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (void)updateCurrentGold:(double)gold giftPrice:(double)price isFromWinning:(BOOL)isFromWinning {
|
- (void)updateCurrentGold:(double)gold giftPrice:(double)price isFromWinning:(BOOL)isFromWinning {
|
||||||
if (isFromWinning) {
|
// if (isFromWinning) {
|
||||||
[self.updateGoldQueue insertObject:[NSString stringWithFormat:@"+ %@", @(gold)] atIndex:0];
|
// [self.updateGoldQueue insertObject:[NSString stringWithFormat:@"+ %@", @(gold)] atIndex:0];
|
||||||
} else {
|
// [self processNextUpdateGold];
|
||||||
[self.updateGoldQueue addObject:@(-price).stringValue];
|
// } else {
|
||||||
self.comboGoldLabel.text = @(gold).stringValue;
|
// [self.updateGoldQueue addObject:@(-price).stringValue];
|
||||||
}
|
// self.comboGoldLabel.text = @(gold).stringValue;
|
||||||
|
// if (!self.isAnimatingUpdateGold) {
|
||||||
|
// [self processNextUpdateGold];
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
if (!self.isAnimatingUpdateGold) {
|
NSString *goldString = isFromWinning ? [NSString stringWithFormat:@"+ %@", @(gold)] : @(-price).stringValue;
|
||||||
|
if (isFromWinning) {
|
||||||
|
[self.updateGoldQueue insertObject:goldString atIndex:0];
|
||||||
[self processNextUpdateGold];
|
[self processNextUpdateGold];
|
||||||
|
} else {
|
||||||
|
[self.updateGoldQueue addObject:goldString];
|
||||||
|
self.comboGoldLabel.text = @(gold).stringValue;
|
||||||
|
|
||||||
|
if (!self.isAnimatingUpdateGold) {
|
||||||
|
[self processNextUpdateGold];
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)processNextUpdateGold {
|
- (void)processNextUpdateGold {
|
||||||
|
// if (self.updateGoldQueue.count == 0) {
|
||||||
|
// self.isAnimatingUpdateGold = NO;
|
||||||
|
// return;
|
||||||
|
// }
|
||||||
|
//
|
||||||
|
// NSNumber *goldNum = [self.updateGoldQueue xpSafeObjectAtIndex:0];
|
||||||
|
// [self.updateGoldQueue removeObjectAtIndex:0];
|
||||||
|
//
|
||||||
|
// self.isAnimatingUpdateGold = YES;
|
||||||
|
//
|
||||||
|
// if (goldNum.integerValue < 0) {
|
||||||
|
// self.updateGoldLabel.text = goldNum.stringValue;
|
||||||
|
// [self showGoldUpdateAnimation];
|
||||||
|
// } else {
|
||||||
|
// self.winPriceGoldLabel.text = goldNum.stringValue;
|
||||||
|
// [self showGoldWinPriceAnimation];
|
||||||
|
// }
|
||||||
|
|
||||||
if (self.updateGoldQueue.count == 0) {
|
if (self.updateGoldQueue.count == 0) {
|
||||||
self.isAnimatingUpdateGold = NO;
|
self.isAnimatingUpdateGold = NO;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
NSNumber *goldNum = [self.updateGoldQueue xpSafeObjectAtIndex:0];
|
NSString *goldString = [self.updateGoldQueue xpSafeObjectAtIndex:0];
|
||||||
[self.updateGoldQueue removeObjectAtIndex:0];
|
[self.updateGoldQueue removeObjectAtIndex:0];
|
||||||
|
|
||||||
self.isAnimatingUpdateGold = YES;
|
self.isAnimatingUpdateGold = YES;
|
||||||
|
|
||||||
if (goldNum.integerValue < 0) {
|
BOOL isWinning = [goldString containsString:@"+"]; // 区分正负值
|
||||||
self.updateGoldLabel.textColor = UIColorFromRGB(0xffd54c);
|
UILabel *targetLabel = isWinning ? [self winPriceGoldLabel] : [self updateGoldLabel];
|
||||||
} else {
|
// [self addSubview:targetLabel];
|
||||||
self.updateGoldLabel.textColor = UIColorFromRGB(0xBC36FF);
|
// [targetLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||||
}
|
//// make.trailing.mas_equalTo(self.comboGoldLabel);
|
||||||
self.updateGoldLabel.text = goldNum.stringValue;
|
//// make.bottom.trailing.mas_equalTo(self.comboGoldLabel);
|
||||||
|
// make.leading.mas_equalTo(44);
|
||||||
|
// make.bottom.mas_equalTo(-44);
|
||||||
|
// }];
|
||||||
|
CGFloat offset = isWinning ? -80 : -40;
|
||||||
|
|
||||||
|
[self showGoldAnimationOnLabel:targetLabel withText:goldString offset:offset];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)showGoldAnimationOnLabel:(UILabel *)label withText:(NSString *)text offset:(CGFloat)offset {
|
||||||
|
label.text = text;
|
||||||
|
label.alpha = 0;
|
||||||
|
|
||||||
|
[UIView animateWithDuration:0.2 animations:^{
|
||||||
|
[label mas_updateConstraints:^(MASConstraintMaker *make) {
|
||||||
|
// make.bottom.mas_equalTo(-44 + offset);
|
||||||
|
make.bottom.mas_equalTo(self.comboGoldLabel.mas_bottom).offset(offset);
|
||||||
|
}];
|
||||||
|
label.alpha = 1;
|
||||||
|
[self layoutIfNeeded];
|
||||||
|
} completion:^(BOOL finished) {
|
||||||
|
[UIView animateWithDuration:0.0
|
||||||
|
delay:0.2
|
||||||
|
options:UIViewAnimationOptionCurveLinear
|
||||||
|
animations:^{
|
||||||
|
[label mas_updateConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.bottom.mas_equalTo(self.comboGoldLabel.mas_bottom).offset(0);
|
||||||
|
}];
|
||||||
|
label.alpha = 0;
|
||||||
|
// [self layoutIfNeeded];
|
||||||
|
} completion:^(BOOL finished) {
|
||||||
|
// [label removeFromSuperview];
|
||||||
|
self.isAnimatingUpdateGold = NO;
|
||||||
|
[self processNextUpdateGold];
|
||||||
|
}];
|
||||||
|
// self.isAnimatingUpdateGold = NO;
|
||||||
|
// [self processNextUpdateGold];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)showGoldUpdateAnimation {
|
||||||
self.updateGoldLabel.alpha = 0;
|
self.updateGoldLabel.alpha = 0;
|
||||||
[UIView animateWithDuration:0.1 animations:^{
|
[UIView animateWithDuration:0.1 animations:^{
|
||||||
[self.updateGoldLabel mas_updateConstraints:^(MASConstraintMaker *make) {
|
[self.updateGoldLabel mas_updateConstraints:^(MASConstraintMaker *make) {
|
||||||
make.bottom.mas_equalTo(self.comboGoldLabel.mas_bottom).offset(goldNum.integerValue > 0 ? -60 : -40);;
|
make.bottom.mas_equalTo(self.comboGoldLabel.mas_bottom).offset(-40);;
|
||||||
}];
|
}];
|
||||||
self.updateGoldLabel.alpha = 1;
|
self.updateGoldLabel.alpha = 1;
|
||||||
[self layoutIfNeeded];
|
[self layoutIfNeeded];
|
||||||
@@ -284,7 +364,31 @@
|
|||||||
}];
|
}];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark -
|
- (void)showGoldWinPriceAnimation {
|
||||||
|
self.winPriceGoldLabel.alpha = 0;
|
||||||
|
[UIView animateWithDuration:0.1 animations:^{
|
||||||
|
[self.winPriceGoldLabel mas_updateConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.bottom.mas_equalTo(self.comboGoldLabel.mas_bottom).offset(-60);
|
||||||
|
}];
|
||||||
|
self.winPriceGoldLabel.alpha = 1;
|
||||||
|
[self layoutIfNeeded];
|
||||||
|
} completion:^(BOOL finished) {
|
||||||
|
[UIView animateWithDuration:0.0
|
||||||
|
delay:0.15
|
||||||
|
options:UIViewAnimationOptionCurveLinear
|
||||||
|
animations:^{
|
||||||
|
[self.winPriceGoldLabel mas_updateConstraints:^(MASConstraintMaker *make) {
|
||||||
|
make.bottom.mas_equalTo(self.comboGoldLabel.mas_bottom).offset(0);
|
||||||
|
}];
|
||||||
|
self.winPriceGoldLabel.alpha = 0;
|
||||||
|
[self layoutIfNeeded];
|
||||||
|
} completion:^(BOOL finished) {
|
||||||
|
self.isAnimatingUpdateGold = NO;
|
||||||
|
[self processNextUpdateGold];
|
||||||
|
}];
|
||||||
|
}];
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark -
|
#pragma mark -
|
||||||
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
|
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
|
||||||
// 如果触摸点在 UITextView 或 UICollectionView 内,则不触发手势
|
// 如果触摸点在 UITextView 或 UICollectionView 内,则不触发手势
|
||||||
@@ -323,12 +427,21 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
- (UILabel *)updateGoldLabel {
|
- (UILabel *)updateGoldLabel {
|
||||||
|
// return [UILabel labelInitWithText:@"" font:kFontSemibold(24) textColor:UIColorFromRGB(0xffd54c)];;
|
||||||
if (!_updateGoldLabel) {
|
if (!_updateGoldLabel) {
|
||||||
_updateGoldLabel = [UILabel labelInitWithText:@"" font:kFontSemibold(24) textColor:UIColorFromRGB(0xffd54c)];
|
_updateGoldLabel = [UILabel labelInitWithText:@"" font:kFontSemibold(24) textColor:UIColorFromRGB(0xffd54c)];
|
||||||
}
|
}
|
||||||
return _updateGoldLabel;
|
return _updateGoldLabel;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
- (UILabel *)winPriceGoldLabel {
|
||||||
|
// return [UILabel labelInitWithText:@"" font:kFontSemibold(24) textColor:UIColorFromRGB(0xBC36FF)];
|
||||||
|
if (!_winPriceGoldLabel) {
|
||||||
|
_winPriceGoldLabel = [UILabel labelInitWithText:@"" font:kFontSemibold(24) textColor:UIColorFromRGB(0xBC36FF)];
|
||||||
|
}
|
||||||
|
return _winPriceGoldLabel;
|
||||||
|
}
|
||||||
|
|
||||||
- (SVGAImageView *)playImageView {
|
- (SVGAImageView *)playImageView {
|
||||||
if (_playImageView == nil) {
|
if (_playImageView == nil) {
|
||||||
_playImageView = [[SVGAImageView alloc]init];
|
_playImageView = [[SVGAImageView alloc]init];
|
||||||
@@ -344,8 +457,14 @@
|
|||||||
_countdownRingView = [[CountdownRingView alloc] initWithFrame:CGRectMake(0, 0, kGetScaleWidth(90), kGetScaleWidth(90))
|
_countdownRingView = [[CountdownRingView alloc] initWithFrame:CGRectMake(0, 0, kGetScaleWidth(90), kGetScaleWidth(90))
|
||||||
duration:5];
|
duration:5];
|
||||||
_countdownRingView.userInteractionEnabled = YES;
|
_countdownRingView.userInteractionEnabled = YES;
|
||||||
|
//#if DEBUG
|
||||||
|
// UILongPressGestureRecognizer *longPress = [[UILongPressGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap)];
|
||||||
|
// longPress.minimumPressDuration = 0.2;
|
||||||
|
// [_countdownRingView addGestureRecognizer:longPress];
|
||||||
|
//#else
|
||||||
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap)];
|
UITapGestureRecognizer *tap = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(handleTap)];
|
||||||
[_countdownRingView addGestureRecognizer:tap];
|
[_countdownRingView addGestureRecognizer:tap];
|
||||||
|
//#endif
|
||||||
}
|
}
|
||||||
return _countdownRingView;
|
return _countdownRingView;
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user