371 lines
13 KiB
Objective-C
371 lines
13 KiB
Objective-C
//
|
|
// XPRoomDatingAnimationView.m
|
|
// xplan-ios
|
|
//
|
|
// Created by 冯硕 on 2022/1/5.
|
|
//
|
|
|
|
#import "XPRoomDatingAnimationView.h"
|
|
///Third
|
|
#import <Masonry/Masonry.h>
|
|
#import <SVGA.h>
|
|
#import <SDWebImage/SDWebImage.h>
|
|
///Model
|
|
#import "XPMacro.h"
|
|
#import "ThemeColor.h"
|
|
#import "UIButton+EnlargeTouchArea.h"
|
|
///Model
|
|
#import "DatingInfoModel.h"
|
|
|
|
@interface XPRoomDatingAnimationView ()
|
|
///背景
|
|
@property (nonatomic,strong) UIView *backView;
|
|
///动画管理类
|
|
@property (strong, nonatomic) SVGAParser *parser;
|
|
///播放相亲结果的SVGA
|
|
@property (nonatomic, strong) SVGAImageView *datingSvgaImageView;
|
|
///倒计时的背景
|
|
@property (nonatomic,strong) UIView *cutTimeBackView;
|
|
///倒计时
|
|
@property (nonatomic,strong) UILabel *timeLabel;
|
|
///分割线
|
|
@property (nonatomic,strong) UIView *lineView;
|
|
///关闭的按钮
|
|
@property (nonatomic,strong) UIButton *closeButton;
|
|
///❤的动画
|
|
@property (nonatomic,strong) UIImageView *heartImageView;
|
|
///
|
|
@property (nonatomic,copy) void(^FinishBlock)(BOOL result);
|
|
/// 定时器
|
|
@property (nonatomic,strong) id timer;
|
|
@end
|
|
|
|
@implementation XPRoomDatingAnimationView
|
|
|
|
- (instancetype)initWithFrame:(CGRect)frame {
|
|
if (self = [super initWithFrame:frame]) {
|
|
[self addSubview:self.backView];
|
|
[self addSubview:self.datingSvgaImageView];
|
|
[self addSubview:self.cutTimeBackView];
|
|
[self addSubview:self.heartImageView];
|
|
[self.cutTimeBackView addSubview:self.timeLabel];
|
|
[self.cutTimeBackView addSubview:self.lineView];
|
|
[self.cutTimeBackView addSubview:self.closeButton];
|
|
[self initContrations];
|
|
}
|
|
return self;
|
|
}
|
|
#pragma mark - Resonse
|
|
- (void)closetButtonAction:(UIButton *)sender {
|
|
if (self.FinishBlock) {
|
|
[NSObject cancelPreviousPerformRequestsWithTarget:self];
|
|
self.FinishBlock(YES);
|
|
}
|
|
}
|
|
|
|
#pragma mark - Pirvate Method
|
|
- (void)initContrations {
|
|
[self mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
make.width.mas_equalTo(KScreenWidth);
|
|
make.height.mas_equalTo(KScreenHeight);
|
|
}];
|
|
|
|
[self.backView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
make.edges.mas_equalTo(self);
|
|
}];
|
|
|
|
[self.datingSvgaImageView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
make.edges.mas_equalTo(self);
|
|
}];
|
|
|
|
[self.cutTimeBackView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
make.size.mas_equalTo(CGSizeMake(70, 25));
|
|
make.right.mas_equalTo(self).offset(-12);
|
|
make.top.mas_equalTo(self).offset(41 + kSafeAreaTopHeight);
|
|
}];
|
|
|
|
[self.timeLabel mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
make.left.mas_equalTo(self.cutTimeBackView).offset(13);
|
|
make.centerY.mas_equalTo(self.cutTimeBackView);
|
|
}];
|
|
|
|
[self.lineView mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
make.center.mas_equalTo(self.cutTimeBackView);
|
|
make.size.mas_equalTo(CGSizeMake(0.5, 13));
|
|
}];
|
|
|
|
[self.closeButton mas_makeConstraints:^(MASConstraintMaker *make) {
|
|
make.size.mas_equalTo(CGSizeMake(14, 14));
|
|
make.centerY.mas_equalTo(self.cutTimeBackView);
|
|
make.left.mas_equalTo(self.lineView.mas_right).offset(8);
|
|
}];
|
|
}
|
|
|
|
- (void)stopAnimation {
|
|
if (self.FinishBlock) {
|
|
[NSObject cancelPreviousPerformRequestsWithTarget:self];
|
|
self.FinishBlock(YES);
|
|
}
|
|
}
|
|
|
|
- (UIImage *)setCornerWithRadius:(CGFloat)radius andSize:(CGSize)size image:(UIImage *)image {
|
|
//开启图形上下文
|
|
UIGraphicsBeginImageContext(size);
|
|
//绘制圆角矩形
|
|
CGRect rect = CGRectMake(0, 0, size.width, size.height);
|
|
UIBezierPath *path = [UIBezierPath bezierPathWithRoundedRect:rect byRoundingCorners:UIRectCornerAllCorners cornerRadii:CGSizeMake(radius, radius)];
|
|
//将Path添加到上下文中
|
|
CGContextAddPath(UIGraphicsGetCurrentContext(), path.CGPath);
|
|
//裁剪上下文
|
|
CGContextClip(UIGraphicsGetCurrentContext());
|
|
//将图片绘制到上下文中
|
|
[image drawInRect:rect];
|
|
//设置绘制模式
|
|
CGContextDrawPath(UIGraphicsGetCurrentContext(), kCGPathStroke);
|
|
//获取图片
|
|
UIImage *output = UIGraphicsGetImageFromCurrentImageContext();
|
|
//关闭上下文
|
|
UIGraphicsEndImageContext();
|
|
//返回裁剪好的图片
|
|
return output;
|
|
}
|
|
|
|
- (CAAnimationGroup *)createRoomDatingPickAnimatioOriginPoint:(CGPoint)orginPoint destinationPoint:(CGPoint)destinationPoint {
|
|
///刚出来的时候 进行慢慢放大的效果
|
|
CAKeyframeAnimation * scaleAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"];
|
|
scaleAnimation.duration = 0.5;
|
|
scaleAnimation.repeatCount = 1;
|
|
scaleAnimation.values = @[@(0),@(0.2),@(0.4), @(0.6), @(0.8), @(0.9), @(1)];
|
|
scaleAnimation.calculationMode = kCAAnimationCubic;
|
|
scaleAnimation.removedOnCompletion = NO;
|
|
scaleAnimation.fillMode = kCAFillModeForwards;
|
|
///
|
|
CAKeyframeAnimation * transformAnimation = [CAKeyframeAnimation animationWithKeyPath:@"position"];
|
|
transformAnimation.beginTime = 0.5;
|
|
transformAnimation.duration = 1;
|
|
transformAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];;
|
|
transformAnimation.values = @[[NSValue valueWithCGPoint:orginPoint],[NSValue valueWithCGPoint:destinationPoint]];
|
|
transformAnimation.repeatCount = 1;
|
|
transformAnimation.removedOnCompletion = NO;
|
|
transformAnimation.fillMode = kCAFillModeForwards;
|
|
|
|
CAKeyframeAnimation * desScaleformAnimation = [CAKeyframeAnimation animationWithKeyPath:@"transform.scale"];
|
|
desScaleformAnimation.beginTime = 1.5;
|
|
desScaleformAnimation.duration = 0.5;
|
|
desScaleformAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];;
|
|
desScaleformAnimation.values = @[@(1), @(1.2), @(1.4), @(1.6)];
|
|
desScaleformAnimation.repeatCount = 1;
|
|
desScaleformAnimation.removedOnCompletion = NO;
|
|
desScaleformAnimation.fillMode = kCAFillModeForwards;
|
|
|
|
|
|
CAKeyframeAnimation * opacityAnimation = [CAKeyframeAnimation animationWithKeyPath:@"opacity"];
|
|
opacityAnimation.beginTime = 1.5;
|
|
opacityAnimation.duration = 0.5;
|
|
opacityAnimation.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionEaseOut];;
|
|
opacityAnimation.values = @[@(1),@(0.8),@(0.6),@(0)];
|
|
opacityAnimation.repeatCount = 1;
|
|
opacityAnimation.removedOnCompletion = NO;
|
|
opacityAnimation.fillMode = kCAFillModeForwards;
|
|
|
|
|
|
CAAnimationGroup * group = [CAAnimationGroup animation];
|
|
group.animations = @[scaleAnimation, transformAnimation, desScaleformAnimation, opacityAnimation];
|
|
group.duration = 2;
|
|
group.removedOnCompletion = NO;
|
|
group.fillMode = kCAFillModeForwards;
|
|
return group;;
|
|
}
|
|
|
|
- (void)startBeginCutCountWithTotalTime:(int)time {
|
|
__block int totalTime = time;
|
|
dispatch_source_t times = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
|
|
_timer = times;
|
|
dispatch_source_set_timer(times, DISPATCH_TIME_NOW, 1* NSEC_PER_SEC, 0 * NSEC_PER_SEC);
|
|
dispatch_source_set_event_handler(times, ^{
|
|
dispatch_async(dispatch_get_main_queue(), ^{
|
|
if (totalTime <= 5 && totalTime >= 0) {
|
|
///开始显示倒计时
|
|
self.cutTimeBackView.hidden = NO;
|
|
self.timeLabel.text = [NSString stringWithFormat:@"%ds", totalTime];
|
|
}
|
|
if (totalTime <= 0) {
|
|
dispatch_source_cancel(times);
|
|
self.cutTimeBackView.hidden = YES;
|
|
}
|
|
totalTime--;
|
|
});
|
|
});
|
|
dispatch_resume(times);
|
|
}
|
|
|
|
- (void)startPickHeartPersonAnimationOriginPoint:(CGPoint)originPoint targetPoint:(CGPoint)targetPoint {
|
|
if (originPoint.x > 0 && targetPoint.x > 0) {
|
|
self.heartImageView.frame = CGRectMake(0, 0, 55, 55);
|
|
self.heartImageView.hidden = YES;
|
|
self.backView.hidden = YES;
|
|
self.heartImageView.hidden = NO;
|
|
self.heartImageView.center = originPoint;
|
|
CAAnimationGroup * group = [self createRoomDatingPickAnimatioOriginPoint:originPoint destinationPoint:targetPoint];
|
|
[self.heartImageView.layer addAnimation:group forKey:nil];
|
|
[self performSelector:@selector(aniationDidFinish:) withObject:self.heartImageView afterDelay:(2)];
|
|
}
|
|
}
|
|
|
|
- (void)aniationDidFinish:(UIImageView *)giftImageView{
|
|
[giftImageView.layer removeAllAnimations];
|
|
giftImageView.hidden = YES;
|
|
}
|
|
|
|
#pragma mark - Public Method
|
|
|
|
- (void)startAnimationWithModel:(DatingInfoModel *)model finishBlock:(void (^)(BOOL))finishBlock {
|
|
self.FinishBlock = finishBlock;
|
|
if (model.hasHeart) {
|
|
if (model.svgaUrl) {
|
|
[self startPalySVGAWithUrl:model];
|
|
} else {
|
|
///如果是心动选人的话 但是没有SVGA的话 直接结束
|
|
///播完之后直接结束这次
|
|
if (self.FinishBlock) {
|
|
self.FinishBlock(YES);
|
|
}
|
|
}
|
|
} else {
|
|
///不是心动选人的话 那就不用播两次 爱心的动画
|
|
[self startPickHeartPersonAnimationOriginPoint:model.originPoint targetPoint:model.targetPoint];
|
|
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
|
|
///心动结束了 直接结束此次
|
|
if (self.FinishBlock) {
|
|
self.FinishBlock(YES);
|
|
}
|
|
});
|
|
}
|
|
|
|
}
|
|
|
|
///播放SVGA的时候 需要先播放选人的动画
|
|
- (void)startPalySVGAWithUrl:(DatingInfoModel *)model {
|
|
if (model.svgaUrl) {
|
|
self.backView.hidden = NO;
|
|
[[SDWebImageManager sharedManager] loadImageWithURL:[NSURL URLWithString:model.avatar] options:SDWebImageRetryFailed progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
|
|
if (image) {
|
|
image = [self setCornerWithRadius:200 andSize:CGSizeMake(400, 400) image:image];
|
|
[self.datingSvgaImageView setImage:image forKey:@"z_tx"];
|
|
}
|
|
}];
|
|
|
|
NSString * title = model.nickname ? model.nickname : @"";
|
|
if (title.length >= 5) {
|
|
title = [NSString stringWithFormat:@"%@…", [title substringToIndex:5]];
|
|
}
|
|
NSMutableAttributedString * rightAttribut = [[NSMutableAttributedString alloc] initWithString:title];
|
|
[rightAttribut addAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:28], NSForegroundColorAttributeName:[UIColor whiteColor]} range:NSMakeRange(0, title.length)];
|
|
[self.datingSvgaImageView setAttributedText:rightAttribut forKey:@"z_yhname"];
|
|
|
|
[[SDWebImageManager sharedManager] loadImageWithURL:[NSURL URLWithString:model.targetAvatar] options:SDWebImageRetryFailed progress:nil completed:^(UIImage * _Nullable image, NSData * _Nullable data, NSError * _Nullable error, SDImageCacheType cacheType, BOOL finished, NSURL * _Nullable imageURL) {
|
|
if (image) {
|
|
image = [self setCornerWithRadius:200 andSize:CGSizeMake(400, 400) image:image];
|
|
[self.datingSvgaImageView setImage:image forKey:@"y_tx"];
|
|
}
|
|
}];
|
|
NSString * leftTitle = model.targetNickname ? model.targetNickname : @"";
|
|
if (leftTitle.length >= 5) {
|
|
leftTitle = [NSString stringWithFormat:@"%@…", [leftTitle substringToIndex:5]];
|
|
}
|
|
NSMutableAttributedString * leftAttribut = [[NSMutableAttributedString alloc] initWithString:leftTitle];
|
|
[leftAttribut addAttributes:@{NSFontAttributeName:[UIFont systemFontOfSize:28], NSForegroundColorAttributeName:[UIColor whiteColor]} range:NSMakeRange(0, leftTitle.length)];
|
|
[self.datingSvgaImageView setAttributedText:leftAttribut forKey:@"y_yhname"];
|
|
@kWeakify(self);
|
|
[self.parser parseWithURL:[NSURL URLWithString:model.svgaUrl] completionBlock:^(SVGAVideoEntity * _Nonnull videoItem) {
|
|
@kStrongify(self);
|
|
self.datingSvgaImageView.hidden = NO;
|
|
self.datingSvgaImageView.videoItem = videoItem;
|
|
self.datingSvgaImageView.loops = 1;
|
|
self.datingSvgaImageView.alpha = 1;
|
|
self.datingSvgaImageView.clearsAfterStop = YES;
|
|
[ self.datingSvgaImageView startAnimation];
|
|
[self startBeginCutCountWithTotalTime:model.svgaSecond];
|
|
} failureBlock:^(NSError * _Nonnull error) {
|
|
|
|
}];
|
|
[self performSelector:@selector(stopAnimation) withObject:nil afterDelay:model.svgaSecond];
|
|
}
|
|
}
|
|
|
|
- (UIImageView *)heartImageView {
|
|
if (!_heartImageView) {
|
|
_heartImageView = [[UIImageView alloc] init];
|
|
_heartImageView.image = [UIImage imageNamed:@"room_mode_dating_pick_heart"];
|
|
_heartImageView.hidden = YES;
|
|
}
|
|
return _heartImageView;
|
|
}
|
|
|
|
- (UIView *)backView {
|
|
if (!_backView) {
|
|
_backView = [[UIView alloc] init];
|
|
_backView.backgroundColor = UIColorRGBAlpha(0x000000, 0.3);
|
|
_backView.hidden = YES;
|
|
}
|
|
return _backView;
|
|
}
|
|
|
|
- (UILabel *)timeLabel {
|
|
if (!_timeLabel) {
|
|
_timeLabel = [[UILabel alloc] init];
|
|
_timeLabel.text = @"5S";
|
|
_timeLabel.font = [UIFont systemFontOfSize:15];
|
|
_timeLabel.textColor = UIColorFromRGB(0xFFFEFE);
|
|
}
|
|
return _timeLabel;
|
|
}
|
|
|
|
- (UIView *)cutTimeBackView {
|
|
if (!_cutTimeBackView) {
|
|
_cutTimeBackView = [[UIView alloc] init];
|
|
_cutTimeBackView.backgroundColor = UIColorRGBAlpha(0x000000, 0.3);
|
|
_cutTimeBackView.layer.masksToBounds = YES;
|
|
_cutTimeBackView.layer.cornerRadius = 25/2;
|
|
_cutTimeBackView.hidden = YES;
|
|
}
|
|
return _cutTimeBackView;
|
|
}
|
|
|
|
- (UIButton *)closeButton {
|
|
if (!_closeButton) {
|
|
_closeButton = [UIButton buttonWithType: UIButtonTypeCustom];
|
|
[_closeButton setImage:[UIImage imageNamed:@"common_close_white"] forState:UIControlStateNormal];
|
|
[_closeButton addTarget:self action:@selector(closetButtonAction:) forControlEvents:UIControlEventTouchUpInside];
|
|
[_closeButton setEnlargeEdgeWithTop:10 right:10 bottom:10 left:10];
|
|
}
|
|
return _closeButton;
|
|
}
|
|
|
|
- (UIView *)lineView {
|
|
if (!_lineView) {
|
|
_lineView = [[UIView alloc] init];
|
|
_lineView.backgroundColor = UIColor.whiteColor;
|
|
}
|
|
return _lineView;
|
|
}
|
|
|
|
- (SVGAParser *)parser {
|
|
if (!_parser) {
|
|
_parser = [[SVGAParser alloc]init];
|
|
}
|
|
return _parser;
|
|
}
|
|
|
|
- (SVGAImageView *)datingSvgaImageView {
|
|
if (!_datingSvgaImageView) {
|
|
_datingSvgaImageView = [[SVGAImageView alloc]init];
|
|
_datingSvgaImageView.backgroundColor = [UIColor clearColor];
|
|
_datingSvgaImageView.frame = self.bounds;
|
|
_datingSvgaImageView.userInteractionEnabled = YES;
|
|
}
|
|
return _datingSvgaImageView;
|
|
}
|
|
|
|
@end
|