fix: 优化送礼的内存效率 |
TODO:调整 combo 时的金币变动效果
This commit is contained in:
@@ -500,6 +500,8 @@
|
||||
4C6E1F752CEAEC3C0073D0A3 /* ShoppingMallTagView.m in Sources */ = {isa = PBXBuildFile; fileRef = 4C6E1F742CEAEC3C0073D0A3 /* ShoppingMallTagView.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 */; };
|
||||
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 */; };
|
||||
4CC6195A2CEC7770008C1EE8 /* MyDressingDataPresent.m in Sources */ = {isa = PBXBuildFile; fileRef = 4CC619592CEC7770008C1EE8 /* MyDressingDataPresent.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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
@@ -8271,6 +8277,10 @@
|
||||
E8998D7F28597B0300C68558 /* XPRoomLuckyBigPrizeView.m */,
|
||||
E838D99E275E1BF60079E0B5 /* XPRoomAnimationView.h */,
|
||||
E838D99F275E1BF60079E0B5 /* XPRoomAnimationView.m */,
|
||||
4C71C6A02D06DB3D00ECCA24 /* GiftAnimationManager.h */,
|
||||
4C71C6A12D06DB3D00ECCA24 /* GiftAnimationManager.m */,
|
||||
4C71C69D2D069D2B00ECCA24 /* GiftAnimationHelper.h */,
|
||||
4C71C69E2D069D2B00ECCA24 /* GiftAnimationHelper.m */,
|
||||
23E9EA782A8385CC00B792F2 /* XPTreasureFairyGiftView.h */,
|
||||
23E9EA772A8385CB00B792F2 /* XPTreasureFairyGiftView.m */,
|
||||
E8E21A9928B4BD92008F7C9D /* XPRoomGraffitiGiftAnimationView.h */,
|
||||
@@ -12378,6 +12388,7 @@
|
||||
238B37C52AC55A2C00BFC9D5 /* XPTreasureFairyMoreView.m in Sources */,
|
||||
E811FFF72742367B00918544 /* XPGiftEmptyCollectionViewCell.m in Sources */,
|
||||
189DD67E26E1FD8900AB55B1 /* UIImage+Utils.m in Sources */,
|
||||
4C71C6A22D06DB3D00ECCA24 /* GiftAnimationManager.m in Sources */,
|
||||
E82D5C73276AE94800858D6D /* CarModel.m in Sources */,
|
||||
E85E7B0B2A4EB0D200B6D00A /* XPGuildSetNamePresenter.m in Sources */,
|
||||
E87E62762A3F5907002F68C9 /* XPNewHomePlayTableViewCell.m in Sources */,
|
||||
@@ -12758,6 +12769,7 @@
|
||||
E81DCCD0282B63FD0039E5C5 /* XPMomentsRecommendViewController.m in Sources */,
|
||||
9B7D804A2753783D003DAC0C /* SessionViewController.m in Sources */,
|
||||
E85E7BA92A4EC99300B6D00A /* XPMineConfirmGiveDiamondView.m in Sources */,
|
||||
4C71C69F2D069D2B00ECCA24 /* GiftAnimationHelper.m in Sources */,
|
||||
54C9A1102C3D3E1700C6D970 /* XPMineGameMateOrderView.m in Sources */,
|
||||
E85E7BA72A4EC99300B6D00A /* XPMineGiveDiamondPasswordView.m in Sources */,
|
||||
54283CEE2CE48B97009729B5 /* ShoppingMallDataPresent.m in Sources */,
|
||||
|
@@ -21,8 +21,8 @@
|
||||
#import "ThirdUserInfo.h"
|
||||
#import "AccountModel.h"
|
||||
#import "DESEncrypt.h"
|
||||
#import <FBSDKCoreKit/FBSDKCoreKit.h>
|
||||
#import <FBSDKLoginKit/FBSDKLoginKit.h>
|
||||
//#import <FBSDKCoreKit/FBSDKCoreKit.h>
|
||||
//#import <FBSDKLoginKit/FBSDKLoginKit.h>
|
||||
#import "YuMi-swift.h"
|
||||
#import "FeedBackConfigModel.h"
|
||||
|
||||
@@ -33,25 +33,25 @@
|
||||
- (instancetype)init{
|
||||
self = [super init];
|
||||
if(self){
|
||||
[[NSNotificationCenter defaultCenter] addObserverForName:FBSDKProfileDidChangeNotification
|
||||
object:nil
|
||||
queue:[NSOperationQueue mainQueue]
|
||||
usingBlock:
|
||||
^(NSNotification *notification) {
|
||||
if ([FBSDKProfile currentProfile]) {
|
||||
//获取当前用户名
|
||||
[FBSDKProfile loadCurrentProfileWithCompletion:
|
||||
^(FBSDKProfile *profile, NSError *error) {
|
||||
if (profile) {
|
||||
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
AccountInfoStorage *accountStorage = [AccountInfoStorage instance];
|
||||
accountStorage.thirdUserInfo.userName = profile.name;
|
||||
accountStorage.thirdUserInfo.avatarUrl = profile.imageURL.absoluteString;
|
||||
});
|
||||
}
|
||||
}];
|
||||
}
|
||||
}];
|
||||
// [[NSNotificationCenter defaultCenter] addObserverForName:FBSDKProfileDidChangeNotification
|
||||
// object:nil
|
||||
// queue:[NSOperationQueue mainQueue]
|
||||
// usingBlock:
|
||||
// ^(NSNotification *notification) {
|
||||
// if ([FBSDKProfile currentProfile]) {
|
||||
// //获取当前用户名
|
||||
// [FBSDKProfile loadCurrentProfileWithCompletion:
|
||||
// ^(FBSDKProfile *profile, NSError *error) {
|
||||
// if (profile) {
|
||||
// dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
|
||||
// AccountInfoStorage *accountStorage = [AccountInfoStorage instance];
|
||||
// accountStorage.thirdUserInfo.userName = profile.name;
|
||||
// accountStorage.thirdUserInfo.avatarUrl = profile.imageURL.absoluteString;
|
||||
// });
|
||||
// }
|
||||
// }];
|
||||
// }
|
||||
// }];
|
||||
}
|
||||
return self;
|
||||
}
|
||||
@@ -200,31 +200,31 @@
|
||||
}];
|
||||
}
|
||||
-(void)thirdLoginByFBWithPresentingViewController:(UIViewController *)presentingViewController {
|
||||
[FBSDKProfile enableUpdatesOnAccessTokenChange:YES];
|
||||
[FBSDKAccessToken setCurrentAccessToken:nil];
|
||||
FBSDKLoginManager *manager = [[FBSDKLoginManager alloc] init];
|
||||
[manager logOut];
|
||||
[XNDJTDDLoadingTool showOnlyView:kWindow];
|
||||
@kWeakify(self);
|
||||
[manager logInWithPermissions:@[@"public_profile"]
|
||||
fromViewController:presentingViewController
|
||||
handler:^(FBSDKLoginManagerLoginResult * _Nullable result, NSError * _Nullable error) {
|
||||
@kStrongify(self);
|
||||
if (error) {
|
||||
[XNDJTDDLoadingTool hideOnlyView:kWindow];
|
||||
[[self getView] showErrorToast:YMLocalizedString(@"LoginPresenter1")];
|
||||
} else if (result.isCancelled) {
|
||||
[XNDJTDDLoadingTool hideOnlyView:kWindow];
|
||||
[[self getView] showErrorToast:YMLocalizedString(@"LoginPresenter0")];
|
||||
} else {
|
||||
ThirdUserInfo * userInfo = [[ThirdUserInfo alloc] init];
|
||||
userInfo.openid = result.token.userID;
|
||||
userInfo.access_token = result.token.tokenString;
|
||||
userInfo.unionid = result.token.userID;
|
||||
[AccountInfoStorage instance].thirdUserInfo = userInfo;
|
||||
[self loginWithThirdPartWithType:ThirdLoginType_FB];
|
||||
}
|
||||
}];
|
||||
// [FBSDKProfile enableUpdatesOnAccessTokenChange:YES];
|
||||
// [FBSDKAccessToken setCurrentAccessToken:nil];
|
||||
// FBSDKLoginManager *manager = [[FBSDKLoginManager alloc] init];
|
||||
// [manager logOut];
|
||||
// [XNDJTDDLoadingTool showOnlyView:kWindow];
|
||||
// @kWeakify(self);
|
||||
// [manager logInWithPermissions:@[@"public_profile"]
|
||||
// fromViewController:presentingViewController
|
||||
// handler:^(FBSDKLoginManagerLoginResult * _Nullable result, NSError * _Nullable error) {
|
||||
// @kStrongify(self);
|
||||
// if (error) {
|
||||
// [XNDJTDDLoadingTool hideOnlyView:kWindow];
|
||||
// [[self getView] showErrorToast:YMLocalizedString(@"LoginPresenter1")];
|
||||
// } else if (result.isCancelled) {
|
||||
// [XNDJTDDLoadingTool hideOnlyView:kWindow];
|
||||
// [[self getView] showErrorToast:YMLocalizedString(@"LoginPresenter0")];
|
||||
// } else {
|
||||
// ThirdUserInfo * userInfo = [[ThirdUserInfo alloc] init];
|
||||
// userInfo.openid = result.token.userID;
|
||||
// userInfo.access_token = result.token.tokenString;
|
||||
// userInfo.unionid = result.token.userID;
|
||||
// [AccountInfoStorage instance].thirdUserInfo = userInfo;
|
||||
// [self loginWithThirdPartWithType:ThirdLoginType_FB];
|
||||
// }
|
||||
// }];
|
||||
}
|
||||
-(void)thirdLoginByGoogleWithPresentingViewController:(UIViewController *)presentingViewController configuration:(GIDConfiguration *)configuration{
|
||||
@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 "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
|
||||
|
||||
// 会命中混淆,model 单独出来
|
||||
@property (nonatomic, copy) NSString *times;
|
||||
@property (nonatomic, copy) NSString *avatar;
|
||||
@property (nonatomic, copy) NSString *coins;
|
||||
@property (nonatomic, copy) NSDictionary *giftNameMap;
|
||||
@property (nonatomic, copy) NSString *roomUid;
|
||||
|
||||
- (NSString *)giftName;
|
||||
@property (nonatomic, copy, readonly) NSString *times;
|
||||
@property (nonatomic, copy, readonly) NSString *avatar;
|
||||
@property (nonatomic, copy, readonly) NSString *coins;
|
||||
@property (nonatomic, copy, readonly) NSDictionary *giftNameMap;
|
||||
@property (nonatomic, copy, readonly) NSString *roomUid;
|
||||
@property (nonatomic, copy, readonly) NSString *giftName;
|
||||
|
||||
@end
|
||||
|
||||
|
||||
@implementation LuckyGiftWinningBannerViewModel
|
||||
|
||||
+ (NSDictionary *)replacedKeyFromPropertyName {
|
||||
return @{
|
||||
@"avatar":@"sender.avatar"
|
||||
};
|
||||
return @{@"avatar": @"sender.avatar"};
|
||||
}
|
||||
|
||||
- (NSString *)giftName {
|
||||
if ([self.giftNameMap.allKeys containsObject:@"ar"] && isMSRTL()) {
|
||||
if (isMSRTL() && [self.giftNameMap[@"ar"] length]) {
|
||||
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
|
||||
@@ -52,13 +56,11 @@
|
||||
@property (nonatomic, strong) LuckyGiftWinningBannerViewModel *model;
|
||||
@property (nonatomic, strong) UIImageView *backgroundImageView;
|
||||
@property (nonatomic, strong) UIImageView *ballImageView;
|
||||
@property (nonatomic, strong) NetImageView *avatarImage;
|
||||
@property (nonatomic, strong) NetImageView *avatarImageView;
|
||||
@property (nonatomic, strong) UILabel *giftNameLabel;
|
||||
@property (nonatomic, strong) UILabel *timesLabel;
|
||||
@property (nonatomic, strong) UILabel *coinsLabel;
|
||||
|
||||
@property (nonatomic, assign) NSInteger currentRoomUid;
|
||||
|
||||
@property (nonatomic, copy) void(^completeDisplay)(void);
|
||||
@property (nonatomic, copy) void(^exitCurrentRoom)(void);
|
||||
|
||||
@@ -71,39 +73,66 @@
|
||||
with:(AttachmentModel *)attachment
|
||||
complete:(void(^)(void))complete
|
||||
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];
|
||||
|
||||
CGFloat width = kGetScaleWidth(346.5);
|
||||
CGFloat height = kGetScaleWidth(82.5);
|
||||
LuckyGiftWinningBannerView *bannerView = [[LuckyGiftWinningBannerView alloc] initWithFrame:CGRectMake(KScreenWidth, 80, width, height)];
|
||||
CGFloat width = kGetScaleWidth(kBannerWidth);
|
||||
CGFloat height = kGetScaleWidth(kBannerHeight);
|
||||
CGRect frame = CGRectMake(KScreenWidth, kBannerTopMargin, width, height);
|
||||
|
||||
LuckyGiftWinningBannerView *bannerView = [[LuckyGiftWinningBannerView alloc] initWithFrame:frame];
|
||||
bannerView.model = model;
|
||||
bannerView.completeDisplay = complete;
|
||||
bannerView.exitCurrentRoom = exit;
|
||||
bannerView.currentRoomUid = roomUid;
|
||||
[superView addSubview:bannerView];
|
||||
|
||||
@kWeakify(bannerView);
|
||||
[UIView animateWithDuration:0.25 animations:^{
|
||||
bannerView.center = CGPointMake(superView.center.x, height/2 + 80);
|
||||
[bannerView animateDisplay];
|
||||
}
|
||||
|
||||
- (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) {
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
[UIView animateWithDuration:0.25 delay:0 options:UIViewAnimationOptionCurveEaseInOut animations:^{
|
||||
bannerView.frame = CGRectMake(-KScreenWidth, 80, width, height);
|
||||
} completion:^(BOOL finished) {
|
||||
@kStrongify(bannerView);
|
||||
[bannerView removeFromSuperview];
|
||||
if (bannerView.completeDisplay) {
|
||||
bannerView.completeDisplay();
|
||||
}
|
||||
}];
|
||||
@kStrongify(self);
|
||||
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(kDisplayDuration * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
||||
[self animateDisappear];
|
||||
});
|
||||
}];
|
||||
}
|
||||
|
||||
- (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 {
|
||||
_model = model;
|
||||
self.avatarImage.imageUrl = model.avatar;
|
||||
self.avatarImageView.imageUrl = model.avatar;
|
||||
self.giftNameLabel.text = [model giftName];
|
||||
self.timesLabel.text = model.times;
|
||||
self.coinsLabel.text = [NSString formatNumberToKOrM:model.coins];
|
||||
@@ -127,13 +156,13 @@ exitCurrentRoom:(void(^)(void))exit {
|
||||
return;
|
||||
}
|
||||
|
||||
__block NSString *targetRoomUid = self.model.roomUid;
|
||||
@kWeakify(self);
|
||||
[TTPopup alertWithMessage:YMLocalizedString(@"Combo_10") confirmHandler:^{
|
||||
@kStrongify(self);
|
||||
if (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(), ^{
|
||||
[XPRoomViewController openRoom:targetRoomUid
|
||||
viewController:[XCCurrentVCStackManager shareManager].getCurrentVC];
|
||||
@@ -153,8 +182,8 @@ exitCurrentRoom:(void(^)(void))exit {
|
||||
make.width.mas_equalTo(self.ballImageView.mas_height);
|
||||
}];
|
||||
|
||||
[self addSubview:self.avatarImage];
|
||||
[self.avatarImage mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
[self addSubview:self.avatarImageView];
|
||||
[self.avatarImageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.leading.mas_equalTo(kGetScaleWidth(8));
|
||||
make.top.mas_equalTo(kGetScaleWidth(24));
|
||||
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]];
|
||||
[self addSubview:titleLabel_1];
|
||||
[titleLabel_1 mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.top.mas_equalTo(self.avatarImage).offset(2);
|
||||
make.leading.mas_equalTo(self.avatarImage.mas_trailing).offset(10);
|
||||
make.top.mas_equalTo(self.avatarImageView).offset(2);
|
||||
make.leading.mas_equalTo(self.avatarImageView.mas_trailing).offset(10);
|
||||
}];
|
||||
|
||||
[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]];
|
||||
[self addSubview:titleLabel_2];
|
||||
[titleLabel_2 mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.bottom.mas_equalTo(self.avatarImage.mas_bottom).offset(-2);
|
||||
make.leading.mas_equalTo(self.avatarImage.mas_trailing).offset(10);
|
||||
make.bottom.mas_equalTo(self.avatarImageView.mas_bottom).offset(-2);
|
||||
make.leading.mas_equalTo(self.avatarImageView.mas_trailing).offset(10);
|
||||
}];
|
||||
|
||||
[self addSubview:self.timesLabel];
|
||||
@@ -226,19 +255,17 @@ exitCurrentRoom:(void(^)(void))exit {
|
||||
return _ballImageView;
|
||||
}
|
||||
|
||||
- (NetImageView *)avatarImage {
|
||||
if (!_avatarImage) {
|
||||
- (NetImageView *)avatarImageView {
|
||||
if (!_avatarImageView) {
|
||||
NetImageConfig * config = [[NetImageConfig alloc]init];
|
||||
config.placeHolder = [UIImageConstant defaultAvatarPlaceholder];
|
||||
config.imageType = ImageTypeCornerAvatar;
|
||||
_avatarImage = [[NetImageView alloc] initWithConfig:config];
|
||||
_avatarImage.backgroundColor = [UIColor clearColor];
|
||||
_avatarImage.contentMode = UIViewContentModeScaleAspectFill;
|
||||
_avatarImage.layer.cornerRadius = kGetScaleWidth(43/2);
|
||||
_avatarImage.layer.masksToBounds = YES;
|
||||
_avatarImage.clipsToBounds = YES;
|
||||
_avatarImageView = [[NetImageView alloc] initWithConfig:config];
|
||||
_avatarImageView.backgroundColor = [UIColor clearColor];
|
||||
_avatarImageView.contentMode = UIViewContentModeScaleAspectFill;
|
||||
[_avatarImageView setCornerRadius:kGetScaleWidth(43/2)];
|
||||
}
|
||||
return _avatarImage;
|
||||
return _avatarImageView;
|
||||
}
|
||||
|
||||
- (UILabel *)giftNameLabel {
|
||||
|
@@ -115,14 +115,6 @@
|
||||
[stackView addArrangedSubview:self.coinIcon];
|
||||
[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];
|
||||
stackView_2.spacing = 4;
|
||||
[self addSubview:stackView_2];
|
||||
@@ -149,10 +141,6 @@
|
||||
[[NSNotificationCenter defaultCenter] postNotificationName:@"receiveLuckGiftWinning" object:model.coins];
|
||||
}
|
||||
|
||||
- (void)display {
|
||||
|
||||
}
|
||||
|
||||
#pragma mark -
|
||||
- (UIImageView *)coinIcon {
|
||||
if (!_coinIcon) {
|
||||
|
@@ -79,6 +79,9 @@
|
||||
#import "GameUniversalBannerView.h"
|
||||
#import "RoomHighValueGiftBannerAnimation.h"
|
||||
|
||||
#import "GiftAnimationHelper.h"
|
||||
#import "GiftAnimationManager.h"
|
||||
|
||||
@interface XPRoomAnimationView ()<
|
||||
SVGAPlayerDelegate,
|
||||
NIMBroadcastManagerDelegate,
|
||||
@@ -90,7 +93,9 @@ XPRoomStarKitchenBannerViewDelegate,
|
||||
PAGViewListener,
|
||||
XPRoomAnchorRankBannerViewDelegate,
|
||||
PIRoomGiftBroadcastWindowDelegate,
|
||||
PIUniversalBannerViewDelegate>
|
||||
PIUniversalBannerViewDelegate,
|
||||
GiftAnimationDelegate>
|
||||
|
||||
///展示的不同层级
|
||||
///最底层的
|
||||
@property (nonatomic,strong) XPRoomAnimationHitView * lowLevelView;
|
||||
@@ -116,24 +121,17 @@ PIUniversalBannerViewDelegate>
|
||||
///代理
|
||||
@property (nonatomic,weak) id<RoomHostDelegate>delegate;
|
||||
|
||||
///复用池
|
||||
@property (strong,nonatomic)NSMutableSet * bannerDequePool;
|
||||
///可见池
|
||||
@property (strong,nonatomic)NSMutableSet * bannerVisiablePool;
|
||||
///礼物定时器 6s刷新一次
|
||||
@property (nonatomic,strong)dispatch_source_t giftEffectTimer;
|
||||
|
||||
|
||||
#pragma mark - 送礼物的动画的
|
||||
///礼物的队列
|
||||
@property (nonatomic,strong) NSMutableArray<GiftReceiveInfoModel *> *giftQueue;
|
||||
///定时器
|
||||
@property (nonatomic ,strong)dispatch_source_t giftTimer;
|
||||
///复用池 应为送礼物的动画是一个很频繁的事情 所以可以减少内存的消耗
|
||||
@property (nonatomic,strong) NSMutableSet<NetImageView *> * giftReuseArray;
|
||||
///可见池
|
||||
@property (nonatomic,strong) NSMutableSet<NetImageView *> * giftVisibleArray;
|
||||
|
||||
//@property (nonatomic,strong) NSMutableArray<GiftReceiveInfoModel *> *giftQueue;
|
||||
/////定时器
|
||||
//@property (nonatomic ,strong)dispatch_source_t giftTimer;
|
||||
@property(nonatomic, strong) GiftAnimationHelper *giftAnimationHelper;
|
||||
@property(nonatomic, strong) GiftAnimationManager *giftAnimationManager;
|
||||
///大礼物是否正在播放
|
||||
@property (nonatomic,assign) BOOL isLargeGiftAnimating;
|
||||
#pragma mark - 进房座驾动画的
|
||||
@@ -205,10 +203,10 @@ PIUniversalBannerViewDelegate>
|
||||
self.giftEffectTimer = nil;
|
||||
}
|
||||
|
||||
if(self.giftTimer != nil){
|
||||
dispatch_source_cancel(self.giftTimer);
|
||||
self.giftTimer = nil;
|
||||
}
|
||||
// if(self.giftTimer != nil){
|
||||
// dispatch_source_cancel(self.giftTimer);
|
||||
// self.giftTimer = nil;
|
||||
// }
|
||||
[self.giftPagView removeListener:self];
|
||||
}
|
||||
- (instancetype)initWithDelegate:(id<RoomHostDelegate>)delegate {
|
||||
@@ -216,9 +214,14 @@ PIUniversalBannerViewDelegate>
|
||||
if (self) {
|
||||
[[NIMSDK sharedSDK].broadcastManager addDelegate:self];
|
||||
self.delegate = delegate;
|
||||
|
||||
[self initSubViews];
|
||||
[self initSubViewConstraints];
|
||||
|
||||
self.giftAnimationHelper = [[GiftAnimationHelper alloc] init];
|
||||
self.giftAnimationManager = [[GiftAnimationManager alloc] initWithContainerView:self.lowLevelView];
|
||||
self.giftAnimationManager.delegate = self;
|
||||
|
||||
_roomEffectModelsQueueV2 = [NSMutableArray array];
|
||||
_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.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 (!self.delegate.getRoomInfo.hasAnimationEffect) {return;}
|
||||
@@ -1662,10 +1669,11 @@ PIUniversalBannerViewDelegate>
|
||||
///在最外面判断是否可以拿到那个礼物 后面使用就不用判断了
|
||||
receiveInfo.gift = giftInfo;
|
||||
receiveInfo.isLuckyBagGift = (attachment.second == Custom_Message_Sub_AllMicroLuckySend || attachment.second == Custom_Message_Sub_AllBatchMicroLuckySend || attachment.second == Custom_Message_Sub_Gift_LuckySend);
|
||||
[self.giftQueue addObject:receiveInfo];
|
||||
if (self.giftTimer == nil && self.giftQueue > 0) {
|
||||
[self startGiftQueueTimer];
|
||||
}
|
||||
[self.giftAnimationManager enqueueGift:receiveInfo];
|
||||
// [self.giftQueue addObject:receiveInfo];
|
||||
// if (self.giftTimer == nil && self.giftQueue > 0) {
|
||||
// [self startGiftQueueTimer];
|
||||
// }
|
||||
}
|
||||
|
||||
#pragma mark - 收到礼物展示动画
|
||||
@@ -1693,260 +1701,38 @@ PIUniversalBannerViewDelegate>
|
||||
///在最外面判断是否可以拿到那个礼物 后面使用就不用判断了
|
||||
receiveInfo.gift = giftInfo;
|
||||
receiveInfo.isLuckyBagGift = (attachment.second == Custom_Message_Sub_AllMicroLuckySend || attachment.second == Custom_Message_Sub_AllBatchMicroLuckySend || attachment.second == Custom_Message_Sub_Gift_LuckySend);
|
||||
[self.giftQueue addObject:receiveInfo];
|
||||
if (self.giftTimer == nil && self.giftQueue > 0) {
|
||||
[self startGiftQueueTimer];
|
||||
}
|
||||
[self.giftAnimationManager enqueueGift:receiveInfo];
|
||||
// [self.giftQueue addObject:receiveInfo];
|
||||
// if (self.giftTimer == nil && self.giftQueue > 0) {
|
||||
// [self startGiftQueueTimer];
|
||||
// }
|
||||
}
|
||||
|
||||
//扫描礼物队列
|
||||
- (void)startGiftQueueTimer {
|
||||
NSTimeInterval period = 0.5; //设置时间间隔一个礼物动画的时间
|
||||
dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
|
||||
dispatch_source_set_timer(_timer, DISPATCH_TIME_NOW, period * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
|
||||
dispatch_source_set_event_handler(_timer, ^{
|
||||
dispatch_async(dispatch_get_main_queue(), ^{
|
||||
if (self.giftQueue.count) {
|
||||
GiftReceiveInfoModel * receiveInfo = self.giftQueue.firstObject;
|
||||
[self handoutGiftDistributeAnimation:receiveInfo];
|
||||
[self.giftQueue removeObject:receiveInfo];
|
||||
}else {
|
||||
dispatch_source_cancel(_timer);
|
||||
self.giftTimer = nil;
|
||||
}
|
||||
});
|
||||
});
|
||||
dispatch_resume(_timer);
|
||||
self.giftTimer = _timer;
|
||||
}
|
||||
//- (void)startGiftQueueTimer {
|
||||
// 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_set_timer(_timer, DISPATCH_TIME_NOW, period * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
|
||||
// dispatch_source_set_event_handler(_timer, ^{
|
||||
// dispatch_async(dispatch_get_main_queue(), ^{
|
||||
// if (self.giftQueue.count) {
|
||||
// GiftReceiveInfoModel * receiveInfo = self.giftQueue.firstObject;
|
||||
//// [self handoutGiftDistributeAnimation:receiveInfo];
|
||||
// [self.giftAnimationManager enqueueGift:receiveInfo];
|
||||
// [self.giftQueue removeObject:receiveInfo];
|
||||
// }else {
|
||||
// dispatch_source_cancel(_timer);
|
||||
// self.giftTimer = nil;
|
||||
// }
|
||||
// });
|
||||
// });
|
||||
// dispatch_resume(_timer);
|
||||
// self.giftTimer = _timer;
|
||||
//}
|
||||
|
||||
///处理礼物的分发动画
|
||||
- (void)handoutGiftDistributeAnimation:(GiftReceiveInfoModel *)receiveInfo {
|
||||
GiftInfoModel * giftInfo = receiveInfo.gift;
|
||||
NSString * sendUid = receiveInfo.uid;
|
||||
CGPoint starPoint = [self getGiftAnimationPoint:sendUid isEnd:NO];
|
||||
CGPoint endPoint;
|
||||
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 - GiftAnimationManagerDelegate
|
||||
- (CGPoint)animationPointAtStageViewByUid:(NSString *)uid {
|
||||
return [self.delegate animationPointAtStageViewByUid:uid];
|
||||
}
|
||||
|
||||
#pragma mark - 全服礼物 飘屏
|
||||
@@ -1957,7 +1743,9 @@ PIUniversalBannerViewDelegate>
|
||||
if (giftNotifyInfo.ceremonyGift)return;
|
||||
// if(giftNotifyInfo.isHomeShow == YES)return; ///房间外飘屏 在tabbar中监听
|
||||
// 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.animationListA addObject:giftNotifyInfo];
|
||||
@@ -2057,8 +1845,6 @@ PIUniversalBannerViewDelegate>
|
||||
[self.animationListB addObject:prizeModel];
|
||||
}
|
||||
|
||||
|
||||
|
||||
- (void)createBigPrizeAnimation:(PIBaseAnimationViewModel *)prizeModel {
|
||||
|
||||
self.isPlayOfB = YES;
|
||||
@@ -2094,11 +1880,6 @@ PIUniversalBannerViewDelegate>
|
||||
[self.animationListB removeObjectAtIndex:0];
|
||||
}
|
||||
self.isPlayOfB = NO;
|
||||
// if(self.isAnimationListAFinish == YES){
|
||||
// self.isAnimationListAFinish = NO;
|
||||
// [self playAnimationWithModel];
|
||||
// return;
|
||||
// }
|
||||
[self playAnimationWithModel];
|
||||
}
|
||||
}];
|
||||
@@ -3070,19 +2851,6 @@ PIUniversalBannerViewDelegate>
|
||||
return _parser;
|
||||
}
|
||||
|
||||
- (NSMutableSet *)bannerDequePool {
|
||||
if (!_bannerDequePool) {
|
||||
_bannerDequePool = [NSMutableSet set];
|
||||
}
|
||||
return _bannerDequePool;
|
||||
}
|
||||
- (NSMutableSet *)bannerVisiablePool {
|
||||
if (!_bannerVisiablePool) {
|
||||
_bannerVisiablePool = [NSMutableSet set];
|
||||
}
|
||||
return _bannerVisiablePool;
|
||||
}
|
||||
|
||||
- (XPRoomAnimationHitView *)lowLevelView {
|
||||
if (!_lowLevelView) {
|
||||
_lowLevelView = [[XPRoomAnimationHitView alloc] init];
|
||||
@@ -3110,26 +2878,12 @@ PIUniversalBannerViewDelegate>
|
||||
return _highLevleView;
|
||||
}
|
||||
|
||||
- (NSMutableArray<GiftReceiveInfoModel *> *)giftQueue {
|
||||
if (!_giftQueue) {
|
||||
_giftQueue = [NSMutableArray array];
|
||||
}
|
||||
return _giftQueue;
|
||||
}
|
||||
|
||||
- (NSMutableSet<NetImageView *> *)giftReuseArray {
|
||||
if (!_giftReuseArray) {
|
||||
_giftReuseArray = [NSMutableSet set];
|
||||
}
|
||||
return _giftReuseArray;
|
||||
}
|
||||
|
||||
- (NSMutableSet<NetImageView *> *)giftVisibleArray {
|
||||
if (!_giftVisibleArray) {
|
||||
_giftVisibleArray = [NSMutableSet set];
|
||||
}
|
||||
return _giftVisibleArray;
|
||||
}
|
||||
//- (NSMutableArray<GiftReceiveInfoModel *> *)giftQueue {
|
||||
// if (!_giftQueue) {
|
||||
// _giftQueue = [NSMutableArray array];
|
||||
// }
|
||||
// return _giftQueue;
|
||||
//}
|
||||
|
||||
- (NSMutableArray<NSDictionary *> *)carEffectQueue {
|
||||
if (_carEffectQueue == nil) {
|
||||
|
@@ -55,30 +55,64 @@
|
||||
|
||||
#pragma mark - 更新 UI
|
||||
- (void)updateUIWithModel:(GiftReceiveInfoModel *)model {
|
||||
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.cacheIcon = model.avatar;
|
||||
self.giftGiverAvatar.imageUrl = model.avatar;
|
||||
} else {
|
||||
if (![self.cacheAvatar isEqualToString:model.avatar]) {
|
||||
self.cacheIcon = model.avatar;
|
||||
self.giftGiverAvatar.imageUrl = model.avatar;
|
||||
}
|
||||
}
|
||||
// 更新礼物图标
|
||||
@kWeakify(self);
|
||||
[self updateCacheForProperty:self.cacheIcon newValue:model.gift.giftUrl updateBlock:^(NSString *value) {
|
||||
@kStrongify(self);
|
||||
self.giftIcon.imageUrl = value;
|
||||
}];
|
||||
|
||||
// 更新头像
|
||||
[self updateCacheForProperty:self.cacheAvatar newValue:model.avatar updateBlock:^(NSString *value) {
|
||||
@kStrongify(self);
|
||||
self.giftGiverAvatar.imageUrl = value;
|
||||
}];
|
||||
|
||||
// 更新名字
|
||||
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];
|
||||
|
||||
// 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 {
|
||||
@@ -190,7 +224,9 @@
|
||||
|
||||
[self addSubview:self.giftIcon];
|
||||
[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.size.mas_equalTo(CGSizeMake(kGetScaleWidth(48), kGetScaleWidth(48)));
|
||||
}];
|
||||
|
@@ -18,6 +18,7 @@
|
||||
@property (nonatomic, strong) UILabel *comboCountLabel;
|
||||
@property(nonatomic, strong) UILabel *comboGoldLabel;
|
||||
@property(nonatomic, strong) UILabel *updateGoldLabel;
|
||||
@property(nonatomic, strong) UILabel *winPriceGoldLabel;
|
||||
@property (nonatomic, strong) SVGAImageView *playImageView;
|
||||
@property (nonatomic, strong) SVGAVideoEntity *svgaVideoEntity;
|
||||
@property (nonatomic, strong) CountdownRingView *countdownRingView;
|
||||
@@ -25,6 +26,8 @@
|
||||
@property(nonatomic, strong) NSMutableArray *updateGoldQueue;
|
||||
@property(nonatomic, assign) BOOL isAnimatingUpdateGold;
|
||||
|
||||
@property(nonatomic, strong) UIImpactFeedbackGenerator *f;
|
||||
|
||||
@end
|
||||
|
||||
@implementation GiftComboView
|
||||
@@ -39,6 +42,7 @@
|
||||
|
||||
- (instancetype)init {
|
||||
if (self = [super init]) {
|
||||
self.f = [[UIImpactFeedbackGenerator alloc] initWithStyle:UIImpactFeedbackStyleHeavy];
|
||||
self.updateGoldQueue = @[].mutableCopy;
|
||||
[self setupNotification];
|
||||
|
||||
@@ -91,10 +95,6 @@
|
||||
double price = [[dic objectForKey:@"Price"] doubleValue];
|
||||
BOOL isFromWinning = [[dic objectForKey:@"isFromWinning"] boolValue];
|
||||
[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.updateGoldLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
make.centerX.mas_equalTo(bg);
|
||||
make.bottom.mas_equalTo(self.comboGoldLabel.mas_bottom).offset(0);
|
||||
make.trailing.mas_equalTo(self.comboGoldLabel);
|
||||
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(), ^{
|
||||
@kStrongify(self);
|
||||
// 1521 连续震动 3 次
|
||||
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
|
||||
// AudioServicesPlaySystemSound(kSystemSoundID_Vibrate);
|
||||
// AudioServicesPlaySystemSound(SystemSoundID(kSystemSoundID_Vibrate));
|
||||
[self.f impactOccurred];
|
||||
|
||||
[[GiftComboManager sharedManager] sendGift];
|
||||
[self.playImageView startAnimation];
|
||||
@@ -231,39 +239,111 @@
|
||||
}
|
||||
|
||||
- (void)updateCurrentGold:(double)gold giftPrice:(double)price isFromWinning:(BOOL)isFromWinning {
|
||||
if (isFromWinning) {
|
||||
[self.updateGoldQueue insertObject:[NSString stringWithFormat:@"+ %@", @(gold)] atIndex:0];
|
||||
} else {
|
||||
[self.updateGoldQueue addObject:@(-price).stringValue];
|
||||
self.comboGoldLabel.text = @(gold).stringValue;
|
||||
}
|
||||
// if (isFromWinning) {
|
||||
// [self.updateGoldQueue insertObject:[NSString stringWithFormat:@"+ %@", @(gold)] atIndex:0];
|
||||
// [self processNextUpdateGold];
|
||||
// } else {
|
||||
// [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];
|
||||
} else {
|
||||
[self.updateGoldQueue addObject:goldString];
|
||||
self.comboGoldLabel.text = @(gold).stringValue;
|
||||
|
||||
if (!self.isAnimatingUpdateGold) {
|
||||
[self 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) {
|
||||
self.isAnimatingUpdateGold = NO;
|
||||
return;
|
||||
}
|
||||
|
||||
NSNumber *goldNum = [self.updateGoldQueue xpSafeObjectAtIndex:0];
|
||||
NSString *goldString = [self.updateGoldQueue xpSafeObjectAtIndex:0];
|
||||
[self.updateGoldQueue removeObjectAtIndex:0];
|
||||
|
||||
self.isAnimatingUpdateGold = YES;
|
||||
|
||||
if (goldNum.integerValue < 0) {
|
||||
self.updateGoldLabel.textColor = UIColorFromRGB(0xffd54c);
|
||||
} else {
|
||||
self.updateGoldLabel.textColor = UIColorFromRGB(0xBC36FF);
|
||||
}
|
||||
self.updateGoldLabel.text = goldNum.stringValue;
|
||||
BOOL isWinning = [goldString containsString:@"+"]; // 区分正负值
|
||||
UILabel *targetLabel = isWinning ? [self winPriceGoldLabel] : [self updateGoldLabel];
|
||||
// [self addSubview:targetLabel];
|
||||
// [targetLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
||||
//// make.trailing.mas_equalTo(self.comboGoldLabel);
|
||||
//// 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;
|
||||
[UIView animateWithDuration:0.1 animations:^{
|
||||
[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 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 -
|
||||
- (BOOL)gestureRecognizer:(UIGestureRecognizer *)gestureRecognizer shouldReceiveTouch:(UITouch *)touch {
|
||||
// 如果触摸点在 UITextView 或 UICollectionView 内,则不触发手势
|
||||
@@ -323,12 +427,21 @@
|
||||
}
|
||||
|
||||
- (UILabel *)updateGoldLabel {
|
||||
// return [UILabel labelInitWithText:@"" font:kFontSemibold(24) textColor:UIColorFromRGB(0xffd54c)];;
|
||||
if (!_updateGoldLabel) {
|
||||
_updateGoldLabel = [UILabel labelInitWithText:@"" font:kFontSemibold(24) textColor:UIColorFromRGB(0xffd54c)];
|
||||
}
|
||||
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 {
|
||||
if (_playImageView == nil) {
|
||||
_playImageView = [[SVGAImageView alloc]init];
|
||||
@@ -344,8 +457,14 @@
|
||||
_countdownRingView = [[CountdownRingView alloc] initWithFrame:CGRectMake(0, 0, kGetScaleWidth(90), kGetScaleWidth(90))
|
||||
duration:5];
|
||||
_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)];
|
||||
[_countdownRingView addGestureRecognizer:tap];
|
||||
//#endif
|
||||
}
|
||||
return _countdownRingView;
|
||||
}
|
||||
|
Reference in New Issue
Block a user