| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124 |
- //
- // MORingCountdownView.m
- // MiMoLive
- //
- // Created by MiMo on 2025/7/27.
- //
- #import "MORingCountdownView.h"
- @interface MORingCountdownView ()<CAAnimationDelegate>
- @property (nonatomic, strong) CAShapeLayer *backgroundLayer;
- @property (nonatomic, strong) CAShapeLayer *progressLayer;
- @property (nonatomic, strong) CAGradientLayer *gradientLayer;
- @property (nonatomic, assign) CFTimeInterval animationStartTime;
- @property (nonatomic, assign) NSTimeInterval animationDuration;
- @end
- @implementation MORingCountdownView
- - (instancetype)initWithFrame:(CGRect)frame {
- if (self = [super initWithFrame:frame]) {
- _lineWidth = 2.0;
- _ringColor = [MOTools colorWithHexString:@"#FFD74A"];
- _backgroundRingColor = [UIColor whiteColor];
- [self setupLayers];
- }
- return self;
- }
- - (void)setupLayers {
- CGFloat lineWidth = self.lineWidth;
- CGPoint center = CGPointMake(CGRectGetMidX(self.bounds), CGRectGetMidY(self.bounds));
- CGFloat radius = (MIN(self.bounds.size.width, self.bounds.size.height) - lineWidth) / 2.0;
- UIBezierPath *circlePath = [UIBezierPath bezierPathWithArcCenter:center
- radius:radius
- startAngle:-M_PI_2
- endAngle:(3 * M_PI_2)
- clockwise:YES];
- // 背景渐变遮罩层路径
- self.backgroundLayer = [CAShapeLayer layer];
- self.backgroundLayer.path = circlePath.CGPath;
- self.backgroundLayer.strokeColor = self.backgroundRingColor.CGColor;
- self.backgroundLayer.fillColor = UIColor.clearColor.CGColor;
- self.backgroundLayer.lineWidth = lineWidth;
- // 创建渐变背景图层
- self.gradientLayer = [CAGradientLayer layer];
- self.gradientLayer.frame = self.bounds;
- self.gradientLayer.colors = @[
- (__bridge id)[MOTools colorWithHexString:@"#FFF0C7" alpha:0.0].CGColor,
- (__bridge id)[MOTools colorWithHexString:@"#FFF0C7" alpha:0.0].CGColor
- ];
- self.gradientLayer.startPoint = CGPointMake(0.5, 0.13);
- self.gradientLayer.endPoint = CGPointMake(0.5, 1.0);
- self.gradientLayer.locations = @[@(0), @(1.0)];
- self.gradientLayer.mask = self.backgroundLayer;
- [self.layer addSublayer:self.gradientLayer];
- // 进度图层
- self.progressLayer = [CAShapeLayer layer];
- self.progressLayer.path = circlePath.CGPath;
- // self.progressLayer.strokeColor = [MOTools colorWithHexString:@"#FFD74A"].CGColor; // #FFD74A
- self.progressLayer.strokeColor = self.ringColor.CGColor;
- self.progressLayer.fillColor = UIColor.clearColor.CGColor;
- self.progressLayer.lineWidth = lineWidth;
- self.progressLayer.lineCap = kCALineCapRound;
- self.progressLayer.strokeStart = 0;
- self.progressLayer.strokeEnd = 1;
- [self.layer addSublayer:self.progressLayer];
- }
- - (void)reloadAppearance {
- [self.backgroundLayer removeFromSuperlayer];
- [self.progressLayer removeFromSuperlayer];
- [self.gradientLayer removeFromSuperlayer];
- [self setupLayers];
- }
- - (void)startCountdownWithDuration:(NSTimeInterval)duration {
- [self.progressLayer removeAllAnimations];
-
- self.animationStartTime = CACurrentMediaTime(); // 记录开始时间
- self.animationDuration = duration;
- self.progressLayer.strokeStart = 0;
- self.progressLayer.strokeEnd = 1;
- CABasicAnimation *anim = [CABasicAnimation animationWithKeyPath:@"strokeStart"];
- anim.duration = duration;
- anim.fromValue = @(0.0);
- anim.toValue = @(1.0);
- anim.timingFunction = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
- anim.fillMode = kCAFillModeForwards;
- anim.removedOnCompletion = NO;
- anim.delegate = self;
- [self.progressLayer addAnimation:anim forKey:@"ringCountdown"];
-
- }
- - (NSTimeInterval)elapsedAnimationTime {
- return CACurrentMediaTime() - self.animationStartTime;
- }
- // 遵守 <CAAnimationDelegate>
- - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag {
- if (flag) {
- MOLogV(@"动画完成");
- [self stopCountdown];
- }
- }
- - (void)stopCountdown {
- [_progressLayer removeAnimationForKey:@"ringCountdown"];
- if (self.stopBlock) {
- self.stopBlock();
- }
- }
- @end
|