2017-08-01 14:44:03 -07:00

78 lines
2.9 KiB
Objective-C

//
// LOTCircleAnimator.m
// Lottie
//
// Created by brandon_withrow on 7/19/17.
// Copyright © 2017 Airbnb. All rights reserved.
//
#import "LOTCircleAnimator.h"
#import "LOTPointInterpolator.h"
const CGFloat kLOTEllipseControlPointPercentage = 0.55228;
@implementation LOTCircleAnimator {
LOTPointInterpolator *_centerInterpolator;
LOTPointInterpolator *_sizeInterpolator;
BOOL _reversed;
}
- (instancetype _Nonnull )initWithInputNode:(LOTAnimatorNode *_Nullable)inputNode
shapeCircle:(LOTShapeCircle *_Nonnull)shapeCircle {
self = [super initWithInputNode:inputNode keyName:shapeCircle.keyname];
if (self) {
_centerInterpolator = [[LOTPointInterpolator alloc] initWithKeyframes:shapeCircle.position.keyframes];
_sizeInterpolator = [[LOTPointInterpolator alloc] initWithKeyframes:shapeCircle.size.keyframes];
_reversed = shapeCircle.reversed;
}
return self;
}
- (NSDictionary *)valueInterpolators {
return @{@"Size" : _sizeInterpolator,
@"Position" : _centerInterpolator};
}
- (BOOL)needsUpdateForFrame:(NSNumber *)frame {
return [_centerInterpolator hasUpdateForFrame:frame] || [_sizeInterpolator hasUpdateForFrame:frame];
}
- (void)performLocalUpdate {
// Unfortunately we HAVE to manually build out the ellipse.
// Every Apple method constructs from the 3 o-clock position
// After effects contrsucts from the Noon position.
// After effects does clockwise, but also has a flag for reversed.
CGPoint center = [_centerInterpolator pointValueForFrame:self.currentFrame];
CGPoint size = [_sizeInterpolator pointValueForFrame:self.currentFrame];
CGFloat halfWidth = size.x / 2;
CGFloat halfHeight = size.y / 2;
if (_reversed) {
halfWidth = halfWidth * -1;
}
CGPoint circleQ1 = CGPointMake(center.x, center.y - halfHeight);
CGPoint circleQ2 = CGPointMake(center.x + halfWidth, center.y);
CGPoint circleQ3 = CGPointMake(center.x, center.y + halfHeight);
CGPoint circleQ4 = CGPointMake(center.x - halfWidth, center.y);
CGFloat cpW = halfWidth * kLOTEllipseControlPointPercentage;
CGFloat cpH = halfHeight * kLOTEllipseControlPointPercentage;
LOTBezierPath *path = [[LOTBezierPath alloc] init];
path.cacheLengths = self.pathShouldCacheLengths;
[path LOT_moveToPoint:circleQ1];
[path LOT_addCurveToPoint:circleQ2 controlPoint1:CGPointMake(circleQ1.x + cpW, circleQ1.y) controlPoint2:CGPointMake(circleQ2.x, circleQ2.y - cpH)];
[path LOT_addCurveToPoint:circleQ3 controlPoint1:CGPointMake(circleQ2.x, circleQ2.y + cpH) controlPoint2:CGPointMake(circleQ3.x + cpW, circleQ3.y)];
[path LOT_addCurveToPoint:circleQ4 controlPoint1:CGPointMake(circleQ3.x - cpW, circleQ3.y) controlPoint2:CGPointMake(circleQ4.x, circleQ4.y + cpH)];
[path LOT_addCurveToPoint:circleQ1 controlPoint1:CGPointMake(circleQ4.x, circleQ4.y - cpH) controlPoint2:CGPointMake(circleQ1.x - cpW, circleQ1.y)];
self.localPath = path;
}
@end