封装了一个iOS对号成功动画

devtools/2024/10/11 7:31:18/

请添加图片描述

基本思路其实很简单,就是通过贝塞尔曲线画出路径,然后
使用CAShapeLayer 渲染路径,然后通过strokeEnd 动画实现
路径的效果,这里注意,这个过程中过遇到过一个问题,就是
对号动画完成之后,整个对号不见了,后来经过仔细调查,发现,是自己初始化 checkLayer的时候,将strokeEnd属设置为0了,注意,虽然我们是通过"strokeEnd"设置的动画,但是我们进行动画之后,并不会真正的改变layer.strokeEnd属性的值,所以我们初始化对号layer的时候,还是要将strokeEnd设置为1
下面贴出所有代码

//
//  ViewController.m
//  LBProgressCircle
//
//  Created by mac on 2024/5/31.
//#import "ViewController.h"@interface ViewController ()@property (nonatomic, strong) UIView *loadingView;//进度圆环曲线
@property (nonatomic, strong) UIBezierPath *circlePath;
//整个圆环
@property (nonatomic, strong) CAShapeLayer *wholeCircleLayer;
//进度圆环layer
@property (nonatomic, strong) CAShapeLayer *progressLayer;
//对号圆环
@property (nonatomic, strong) CAShapeLayer *checkRoundLayer;
//对号layer
@property (nonatomic, strong) CAShapeLayer *checkLayer;@end@implementation ViewController- (void)viewDidLoad {[super viewDidLoad];self.view.backgroundColor = [UIColor lightGrayColor];[self.view addSubview:self.loadingView];[self.loadingView.layer addSublayer:self.wholeCircleLayer];[self.loadingView.layer addSublayer:self.progressLayer];[self.loadingView.layer addSublayer:self.checkLayer];[self.loadingView.layer addSublayer:self.checkRoundLayer];[self handle];// Do any additional setup after loading the view.
}- (void)handle
{self.progressLayer.strokeEnd = 0;__block CGFloat second = 0;NSTimer *time = [NSTimer scheduledTimerWithTimeInterval:0.1 repeats:YES block:^(NSTimer * _Nonnull timer) {if (second >= 1) {return;}second += 0.1;[self updateProgress:second];}];
}- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{[self handle];
}- (void)updateProgress:(CGFloat)progress
{self.progressLayer.strokeEnd = progress;if (progress >= 1) {[self showProgressCirce:NO];[self.checkRoundLayer addAnimation:[self animation] forKey:@"strokeEnd"];dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{self.checkLayer.hidden = NO;[self.checkLayer addAnimation:[self animation] forKey:@"strokeEnd"];});} else {self.checkLayer.hidden = YES;[self showProgressCirce:YES];}
}- (void)showProgressCirce:(BOOL)showCircle
{self.checkRoundLayer.hidden = showCircle;self.wholeCircleLayer.hidden = !showCircle;self.progressLayer.hidden = !showCircle;
}#pragma mark - lazy load- (UIView *)loadingView
{if (!_loadingView) {_loadingView = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)];_loadingView.backgroundColor = [UIColor blackColor];}return _loadingView;
}- (UIBezierPath *)circlePath
{if (!_circlePath) {_circlePath = [UIBezierPath bezierPathWithArcCenter:CGPointMake(27.5, 44) radius:19 startAngle:-M_PI_2 endAngle:-M_PI_2 + M_PI * 2 clockwise:YES];_circlePath.lineCapStyle = kCGLineCapRound;_circlePath.lineJoinStyle = kCGLineJoinRound;}return _circlePath;
}- (CAShapeLayer *)progressLayer
{if (!_progressLayer) {_progressLayer = [[CAShapeLayer alloc] init];_progressLayer.path = self.circlePath.CGPath;_progressLayer.strokeStart = 0;_progressLayer.strokeEnd = 0;_progressLayer.strokeColor = [UIColor redColor].CGColor;_progressLayer.fillColor = [UIColor clearColor].CGColor;_progressLayer.lineWidth = 2;}return _progressLayer;
}- (CAShapeLayer *)wholeCircleLayer
{if (!_wholeCircleLayer) {_wholeCircleLayer = [[CAShapeLayer alloc] init];_wholeCircleLayer.path = self.circlePath.CGPath;_wholeCircleLayer.strokeStart = 0;_wholeCircleLayer.strokeEnd = 1;_wholeCircleLayer.strokeColor = [[UIColor redColor] colorWithAlphaComponent:0].CGColor;_wholeCircleLayer.fillColor = [UIColor clearColor].CGColor;_wholeCircleLayer.lineWidth = 2;}return _wholeCircleLayer;
}- (CAShapeLayer *)checkRoundLayer
{if (!_checkRoundLayer) {UIBezierPath *path = [UIBezierPath bezierPathWithArcCenter:CGPointMake(27.5, 44) radius:16 startAngle:- M_PI_2 endAngle:- M_PI_2 + M_PI * 2 clockwise:YES];path.lineCapStyle = kCGLineCapRound;path.lineJoinStyle = kCGLineJoinRound;_checkRoundLayer = [[CAShapeLayer alloc] init];_checkRoundLayer.path = path.CGPath;_checkRoundLayer.strokeColor = [UIColor whiteColor].CGColor;_checkRoundLayer.fillColor = [UIColor clearColor].CGColor;_checkRoundLayer.hidden = YES;_checkRoundLayer.lineWidth = 2;}return _checkRoundLayer;
}- (CAShapeLayer *)checkLayer
{if (!_checkLayer) {UIBezierPath *path = [[UIBezierPath alloc] init];path.lineCapStyle = kCGLineCapRound;path.lineJoinStyle = kCGLineJoinRound;[path moveToPoint:CGPointMake(19, 43)];CGPoint pl = CGPointMake(25, 49);[path addLineToPoint:pl];CGPoint p2 = CGPointMake(36, 39);[path addLineToPoint:p2];_checkLayer = [[CAShapeLayer alloc] init];_checkLayer.fillColor = [UIColor clearColor].CGColor;//线条颜色_checkLayer.strokeColor = [UIColor whiteColor].CGColor;_checkLayer.lineWidth = 2;_checkLayer.path = path.CGPath;_checkLayer.hidden = YES;}return _checkLayer;
}- (CABasicAnimation *)animation
{CABasicAnimation *checkAnimation = [CABasicAnimation animationWithKeyPath:@"strokeEnd"];checkAnimation.duration = 0.5;checkAnimation.fromValue = @(0);checkAnimation.toValue = @(1);return checkAnimation;
}@end

http://www.ppmy.cn/devtools/46366.html

相关文章

ABAP 借助公司封装的钉钉URL,封装的RFC给钉钉发送消息

FUNCTION ZRFC_BC_SMSSEND_DINGTALK. *"---------------------------------------------------------------------- *"*"本地接口&#xff1a; *" IMPORTING *" VALUE(DESTUSRID) TYPE CHAR255 *" VALUE(CONTENT) TYPE CHAR255 *&quo…

如何用结构化写好GPT的Prompt提示词

背景 最早接触 Prompt engineering 时, 学到的 Prompt 技巧都是: 你是一个 XX 角色…你是一个有着 X 年经验的 XX 角色…你会 XX, 不要 YY…对于你不会的东西, 不要瞎说!… 对比什么技巧都不用, 直接像使用搜索引擎一样提问, 上面的技巧对于回复的效果确实有着 明显提升. 在看…

创建线程的技术难点

在软件开发中&#xff0c;创建线程并正确地管理它们是一个复杂而关键的任务&#xff0c;涉及的技术难点主要有&#xff1a; 线程同步&#xff1a;当多个线程需要访问共享资源时&#xff0c;必须确保它们以某种方式同步&#xff0c;以避免数据不一致或其他并发问题。例如&#…

Ant Design Vue动态表头并填充数据

导语&#xff1a; 在开发过程中&#xff0c;我们常常会遇到需要展示大量数据的场景&#xff0c;例如商品信息、用户数据等。这些场景下&#xff0c;表格是一个很好的数据展示方式。Ant Design Vue是一款优秀的Vue UI组件库&#xff0c;它提供了丰富的组件&#xff0c;其中就包括…

构建体育直播平台源码:深度解析数据分析模块的核心展示内容

在现代的体育直播平台中&#xff0c;数据分析展示已经成为不可或缺的一部分。如下参考借助“东莞梦幻网络科技”提供的体育直播源码&#xff0c;打造的平台&#xff0c;并通过表格形式为用户列出以下数据分析内容&#xff1a; 1、积分排名&#xff1a;反映了各支队伍在赛季中的…

【JAVA】Java中MyBatis的QueryWrapper的使用

文章目录 前言一、函数解释二、代码实现三、总结 前言 在Java开发中&#xff0c;我们常常需要使用ORM框架来简化数据库操作。MyBatis是一个流行的ORM框架&#xff0c;而MyBatis-Plus是它的一个增强版&#xff0c;提供了更多的便利功能。在这篇博客中&#xff0c;我们将探讨如何…

[数据集][目标检测]航空发动机缺陷检测数据集VOC+YOLO格式291张4类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;291 标注数量(xml文件个数)&#xff1a;291 标注数量(txt文件个数)&#xff1a;291 标注类别…

270 基于matlab的模糊自适应PID控制

基于matlab的模糊自适应PID控制&#xff0c;具有10页报告。传统PID在对象变化时&#xff0c;控制器的参数难以自动调整。将模糊控制与PID控制结合&#xff0c;利用模糊推理方法实现对PID参数的在线自整定。使控制器具有较好的自适应性。使用MATLAB对系统进行仿真&#xff0c;结…