You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

139 lines
5.1 KiB

//
// SVIndefiniteAnimatedView.m
// SVProgressHUD, https://github.com/SVProgressHUD/SVProgressHUD
//
// Copyright (c) 2014-2019 Guillaume Campagna. All rights reserved.
//
#import "SVIndefiniteAnimatedView.h"
#import "SVProgressHUD.h"
@interface SVIndefiniteAnimatedView ()
@property (nonatomic, strong) CAGradientLayer *indefiniteAnimatedGradientLayer;
@end
@implementation SVIndefiniteAnimatedView
- (void)willMoveToSuperview:(UIView*)newSuperview {
if (newSuperview) {
[self layoutAnimatedLayer];
} else {
[_indefiniteAnimatedGradientLayer removeFromSuperlayer];
_indefiniteAnimatedGradientLayer = nil;
}
}
- (void)layoutAnimatedLayer {
CALayer *layer = self.indefiniteAnimatedGradientLayer;
[self.layer addSublayer:layer];
CGFloat widthDiff = CGRectGetWidth(self.bounds) - CGRectGetWidth(layer.bounds);
CGFloat heightDiff = CGRectGetHeight(self.bounds) - CGRectGetHeight(layer.bounds);
layer.position = CGPointMake(CGRectGetWidth(self.bounds) - CGRectGetWidth(layer.bounds) / 2 - widthDiff / 2, CGRectGetHeight(self.bounds) - CGRectGetHeight(layer.bounds) / 2 - heightDiff / 2);
}
- (CAGradientLayer *)indefiniteAnimatedGradientLayer {
if (!_indefiniteAnimatedGradientLayer) {
CGPoint arcCenter = CGPointMake(self.radius+self.strokeThickness/2+5, self.radius+self.strokeThickness/2+5);
UIBezierPath* smoothedPath = [UIBezierPath bezierPathWithArcCenter:arcCenter radius:self.radius startAngle:(CGFloat) (M_PI*3/2) endAngle:(CGFloat) (-0.5 * M_PI) clockwise:NO];
CAShapeLayer *shapeLayer = [CAShapeLayer layer];
shapeLayer.contentsScale = [[UIScreen mainScreen] scale];
shapeLayer.frame = CGRectMake(0.0f, 0.0f, arcCenter.x*2, arcCenter.y*2);
shapeLayer.fillColor = [UIColor clearColor].CGColor;
shapeLayer.strokeColor = self.strokeColor.CGColor;
shapeLayer.lineWidth = self.strokeThickness;
shapeLayer.lineCap = kCALineCapRound;
shapeLayer.lineJoin = kCALineJoinRound;
shapeLayer.path = smoothedPath.CGPath;
shapeLayer.strokeStart = 0.4f;
shapeLayer.strokeEnd = 1.0f;
_indefiniteAnimatedGradientLayer = [CAGradientLayer layer];
_indefiniteAnimatedGradientLayer.startPoint = CGPointMake(0.5f, 0.0f);
_indefiniteAnimatedGradientLayer.endPoint = CGPointMake(0.5f, 1.0f);
_indefiniteAnimatedGradientLayer.frame = shapeLayer.bounds;
_indefiniteAnimatedGradientLayer.colors = [NSArray arrayWithObjects:
(id)[self.strokeColor colorWithAlphaComponent:0.0f].CGColor,
(id)[self.strokeColor colorWithAlphaComponent:0.5f].CGColor,
(id)self.strokeColor.CGColor,
nil];
_indefiniteAnimatedGradientLayer.locations = [NSArray arrayWithObjects:
@(0.25f),
@(0.5f),
@(1.0f),
nil];
_indefiniteAnimatedGradientLayer.mask = shapeLayer;
NSTimeInterval animationDuration = 1;
CAMediaTimingFunction *linearCurve = [CAMediaTimingFunction functionWithName:kCAMediaTimingFunctionLinear];
CABasicAnimation *animation = [CABasicAnimation animationWithKeyPath:@"transform.rotation"];
animation.fromValue = (id) 0;
animation.toValue = @(M_PI*2);
animation.duration = animationDuration;
animation.timingFunction = linearCurve;
animation.removedOnCompletion = NO;
animation.repeatCount = INFINITY;
animation.fillMode = kCAFillModeForwards;
animation.autoreverses = NO;
[_indefiniteAnimatedGradientLayer addAnimation:animation forKey:@"rotate"];
}
return _indefiniteAnimatedGradientLayer;
}
- (void)setFrame:(CGRect)frame {
if (!CGRectEqualToRect(frame, super.frame)) {
[super setFrame:frame];
if (self.superview) {
[self layoutAnimatedLayer];
}
}
}
- (void)setRadius:(CGFloat)radius {
if(radius != _radius) {
_radius = radius;
[_indefiniteAnimatedGradientLayer removeFromSuperlayer];
_indefiniteAnimatedGradientLayer = nil;
if (self.superview) {
[self layoutAnimatedLayer];
}
}
}
- (void)setStrokeColor:(UIColor*)strokeColor {
_strokeColor = strokeColor;
[_indefiniteAnimatedGradientLayer removeFromSuperlayer];
_indefiniteAnimatedGradientLayer = nil;
if (self.superview) {
[self layoutAnimatedLayer];
}
}
- (void)setStrokeThickness:(CGFloat)strokeThickness {
_strokeThickness = strokeThickness;
[_indefiniteAnimatedGradientLayer removeFromSuperlayer];
_indefiniteAnimatedGradientLayer = nil;
if (self.superview) {
[self layoutAnimatedLayer];
}
}
- (CGSize)sizeThatFits:(CGSize)size {
return CGSizeMake((self.radius+self.strokeThickness/2+5)*2, (self.radius+self.strokeThickness/2+5)*2);
}
@end