使用 CAShapeLayer 创建 UIActivityIndicator 动画
Using CAShapeLayer to create UIActivityIndicator animation
我想使用 CAShapeLayer
描边创建看起来像 UIActivityIndicator
动画的动画。
我创建了图层:
self.ovalShapeLayer = [CAShapeLayer layer];
self.ovalShapeLayer.strokeColor = [UIColor redColor].CGColor;
self.ovalShapeLayer.fillColor = [UIColor clearColor].CGColor;
self.ovalShapeLayer.lineWidth = 15.0;
self.ovalShapeLayer.lineDashPattern = @[@1, @9];
self.ovalShapeLayer.lineDashPhase = 20.0;
self.ovalShapeLayer.lineJoin = kCALineJoinBevel;
self.ovalShapeLayer.strokeStart = 0.0;
self.ovalShapeLayer.strokeEnd = 1.0;
self.ovalShapeLayer.path = [UIBezierPath bezierPathWithOvalInRect:self.controlView.bounds].CGPath;
[self.controlView.layer addSublayer:self.ovalShapeLayer];
而且效果很好。我还可以使用
为笔画末端设置动画
[CABasicAnimation animationWithKeyPath:@"strokeEnd"]
但是 UIActivityIndicator
动画更复杂,因为它的破折号正在淡化 in/out,看起来像旋转。您对如何实现该动画有任何想法吗?我正在考虑用新的 CAShapeLayer
创建每个破折号,然后使用 keyframe
不透明度动画,但它似乎是错误的方式。
您可以拍摄附件中的 1 张加载器图像,然后在 z-axis 上旋转该图像。
CABasicAnimation* rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 /* full rotation*/ * rotations * duration ];
rotationAnimation.duration = duration;
rotationAnimation.cumulative = YES;
rotationAnimation.repeatCount = repeat;
[imageView.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
@interface CustomView (){
__weak IBOutlet UIImageView *loaderImageView;
}
@end
@implementation CustomView
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
// Initialization code
// loaderImageView = [[UIImageView alloc] initWithFrame:(CGRect){CGPointZero, 35, 35}];
// loaderImageView.contentMode = UIViewContentModeScaleAspectFit;
// [self addSubview:loaderImageView];
}
return self;
}
- (void) setUp{
CABasicAnimation* rotationAnimation1;
rotationAnimation1 = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation1.toValue = @M_PI_2;
rotationAnimation1.duration = 1.0;
rotationAnimation1.cumulative = YES;
rotationAnimation1.repeatCount = HUGE_VALF;
[loaderImageView.layer addAnimation:rotationAnimation1 forKey:@"rotation"];
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
@end
经过一些研究,我发现很棒 class - CAReplicatorLayer
。
使用 class 我能够创建一个 CALayer
对象并使用 CATransform3D
复制它。
这是我的代码:
self.replicatorLayer = [CAReplicatorLayer layer];
self.replicatorLayer.frame = self.controlView.bounds;
[self.controlView.layer addSublayer:self.replicatorLayer];
self.dashLayer = [CALayer layer];
CGFloat dotSide = 4.0;
self.dashLayer.frame = CGRectMake(CGRectGetMidX(self.replicatorLayer.frame) - dotSide / 2, 0.0, dotSide, dotSide * 4);
self.dashLayer.backgroundColor = [UIColor redColor].CGColor;
self.dashLayer.cornerRadius = 1.5;
self.dashLayer.cornerRadius = 2.5;
[self.replicatorLayer addSublayer:self.dashLayer];
self.replicatorLayer.instanceCount = 12;
self.replicatorLayer.instanceTransform = CATransform3DMakeRotation(M_PI / 6, 0.0, 0.0, 1.0);
self.replicatorLayer.instanceDelay = 1.0 / 12;
动画看起来像这样:
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
animation.fromValue = @(1.0);
animation.toValue = @(0.0);
animation.duration = 1.0;
animation.repeatCount = CGFLOAT_MAX;
[self.dashLayer addAnimation:animation forKey:nil];
很有魅力 ;)
我花了很多时间了解 UIRefreshControl 的工作原理,包括 UIActivityIndicator。最后,我写了一个刷新控件来避免系统刷新控件中的一些问题。这是刷新控件中我的 activity 指标的代码:https://github.com/JohnWong/JWKit/blob/master/refresh-control/JWRefreshIndicatorView.m
如果你使用lldb检查系统activity指标和我的,你会发现它与UIActivityIndicator非常相似。 CAReplicatorLayer
是创建视图的关键。
我想使用 CAShapeLayer
描边创建看起来像 UIActivityIndicator
动画的动画。
我创建了图层:
self.ovalShapeLayer = [CAShapeLayer layer];
self.ovalShapeLayer.strokeColor = [UIColor redColor].CGColor;
self.ovalShapeLayer.fillColor = [UIColor clearColor].CGColor;
self.ovalShapeLayer.lineWidth = 15.0;
self.ovalShapeLayer.lineDashPattern = @[@1, @9];
self.ovalShapeLayer.lineDashPhase = 20.0;
self.ovalShapeLayer.lineJoin = kCALineJoinBevel;
self.ovalShapeLayer.strokeStart = 0.0;
self.ovalShapeLayer.strokeEnd = 1.0;
self.ovalShapeLayer.path = [UIBezierPath bezierPathWithOvalInRect:self.controlView.bounds].CGPath;
[self.controlView.layer addSublayer:self.ovalShapeLayer];
而且效果很好。我还可以使用
为笔画末端设置动画[CABasicAnimation animationWithKeyPath:@"strokeEnd"]
但是 UIActivityIndicator
动画更复杂,因为它的破折号正在淡化 in/out,看起来像旋转。您对如何实现该动画有任何想法吗?我正在考虑用新的 CAShapeLayer
创建每个破折号,然后使用 keyframe
不透明度动画,但它似乎是错误的方式。
您可以拍摄附件中的 1 张加载器图像,然后在 z-axis 上旋转该图像。
CABasicAnimation* rotationAnimation;
rotationAnimation = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation.toValue = [NSNumber numberWithFloat: M_PI * 2.0 /* full rotation*/ * rotations * duration ];
rotationAnimation.duration = duration;
rotationAnimation.cumulative = YES;
rotationAnimation.repeatCount = repeat;
[imageView.layer addAnimation:rotationAnimation forKey:@"rotationAnimation"];
@interface CustomView (){
__weak IBOutlet UIImageView *loaderImageView;
}
@end
@implementation CustomView
- (id)initWithCoder:(NSCoder *)aDecoder
{
self = [super initWithCoder:aDecoder];
if (self) {
// Initialization code
// loaderImageView = [[UIImageView alloc] initWithFrame:(CGRect){CGPointZero, 35, 35}];
// loaderImageView.contentMode = UIViewContentModeScaleAspectFit;
// [self addSubview:loaderImageView];
}
return self;
}
- (void) setUp{
CABasicAnimation* rotationAnimation1;
rotationAnimation1 = [CABasicAnimation animationWithKeyPath:@"transform.rotation.z"];
rotationAnimation1.toValue = @M_PI_2;
rotationAnimation1.duration = 1.0;
rotationAnimation1.cumulative = YES;
rotationAnimation1.repeatCount = HUGE_VALF;
[loaderImageView.layer addAnimation:rotationAnimation1 forKey:@"rotation"];
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
- (void)drawRect:(CGRect)rect
{
// Drawing code
}
*/
@end
经过一些研究,我发现很棒 class - CAReplicatorLayer
。
使用 class 我能够创建一个 CALayer
对象并使用 CATransform3D
复制它。
这是我的代码:
self.replicatorLayer = [CAReplicatorLayer layer];
self.replicatorLayer.frame = self.controlView.bounds;
[self.controlView.layer addSublayer:self.replicatorLayer];
self.dashLayer = [CALayer layer];
CGFloat dotSide = 4.0;
self.dashLayer.frame = CGRectMake(CGRectGetMidX(self.replicatorLayer.frame) - dotSide / 2, 0.0, dotSide, dotSide * 4);
self.dashLayer.backgroundColor = [UIColor redColor].CGColor;
self.dashLayer.cornerRadius = 1.5;
self.dashLayer.cornerRadius = 2.5;
[self.replicatorLayer addSublayer:self.dashLayer];
self.replicatorLayer.instanceCount = 12;
self.replicatorLayer.instanceTransform = CATransform3DMakeRotation(M_PI / 6, 0.0, 0.0, 1.0);
self.replicatorLayer.instanceDelay = 1.0 / 12;
动画看起来像这样:
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"opacity"];
animation.fromValue = @(1.0);
animation.toValue = @(0.0);
animation.duration = 1.0;
animation.repeatCount = CGFLOAT_MAX;
[self.dashLayer addAnimation:animation forKey:nil];
很有魅力 ;)
我花了很多时间了解 UIRefreshControl 的工作原理,包括 UIActivityIndicator。最后,我写了一个刷新控件来避免系统刷新控件中的一些问题。这是刷新控件中我的 activity 指标的代码:https://github.com/JohnWong/JWKit/blob/master/refresh-control/JWRefreshIndicatorView.m
如果你使用lldb检查系统activity指标和我的,你会发现它与UIActivityIndicator非常相似。 CAReplicatorLayer
是创建视图的关键。