note the code
@interface YoYoView() {
CAShapeLayer *_ringLayer;
CAShapeLayer *_ballLayer;
CAShapeLayer *_ballContentLayer;
}
@end
@implementation YoYoView
- (instancetype)initWithFrame:(CGRect)frame {
self = [super initWithFrame:frame];
if (self) {
[self createUI];
[self startAnimation];
}
return self;
}
- (void)createUI {
CGFloat ringLayerRadius = 73;
CGFloat ballLayerRadius = 11;
CGFloat ballContentLayerWidth = 232;
CGRect ringLayerRect = CGRectMake(0, 0, 2 * ringLayerRadius, 2 * ringLayerRadius);
UIBezierPath *path = [UIBezierPath bezierPathWithOvalInRect:ringLayerRect];
_ringLayer = [CAShapeLayer layer];
_ringLayer.path = path.CGPath;
_ringLayer.lineWidth = 22;
_ringLayer.strokeColor = [UIColor redColor].CGColor;
_ringLayer.frame = ringLayerRect;
_ringLayer.fillColor = [UIColor clearColor].CGColor;
_ringLayer.position = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2);
[self.layer addSublayer:_ringLayer];
_ballContentLayer = [CAShapeLayer layer];
_ballContentLayer.frame = CGRectMake(0, 0, ballContentLayerWidth, ballContentLayerWidth);
_ballContentLayer.position = CGPointMake(self.frame.size.width / 2, self.frame.size.height / 2);
[self.layer addSublayer:_ballContentLayer];
[self initRotate];
_ballLayer = [CAShapeLayer layer];
_ballLayer.frame = CGRectMake(0, 0, 2 * ballLayerRadius, 2 * ballLayerRadius);
_ballLayer.cornerRadius = ballLayerRadius;
_ballLayer.backgroundColor = [UIColor redColor].CGColor;
_ballLayer.position = CGPointMake(ballContentLayerWidth / 2, 0);
[_ballContentLayer addSublayer:_ballLayer];
}
- (void)initRotate {
CGAffineTransform transform = CGAffineTransformMakeRotation(M_PI_2 / 2);
_ballContentLayer.affineTransform = transform;
}
- (void)startAnimation {
CAMediaTimingFunction *timingFunction = [CAMediaTimingFunction functionWithControlPoints:0.79 :0.14 :0.123 :0.83];
CABasicAnimation *animation = [CABasicAnimation animation];
animation.keyPath = @"transform.rotation";
animation.duration = 2.5;
animation.repeatCount = INFINITY;
animation.byValue = @(M_PI * 2);
animation.timingFunction = timingFunction;
[_ballContentLayer addAnimation:animation forKey:animation.keyPath];
}
@end