Added mask, matte, line dash, trim support

This commit is contained in:
Brandon Withrow
2016-07-26 16:52:31 -07:00
parent 2191e99fb1
commit d2d4cd40ee
30 changed files with 444 additions and 168 deletions

View File

@@ -35,7 +35,6 @@
620A565F1D1C81750030EBFB /* LAAnimatablePointValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 620A565E1D1C81750030EBFB /* LAAnimatablePointValue.m */; };
620A56621D1C81850030EBFB /* LAAnimatableNumberValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 620A56611D1C81850030EBFB /* LAAnimatableNumberValue.m */; };
620A56651D1C81930030EBFB /* LAAnimatableShapeValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 620A56641D1C81930030EBFB /* LAAnimatableShapeValue.m */; };
620CD7CD1D3415F000055AD1 /* LAAnimatableRectValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 620CD7CC1D3415F000055AD1 /* LAAnimatableRectValue.m */; };
620CD7D01D343A2500055AD1 /* LAAnimatableScaleValue.m in Sources */ = {isa = PBXBuildFile; fileRef = 620CD7CF1D343A2500055AD1 /* LAAnimatableScaleValue.m */; };
620CD7E51D38180800055AD1 /* LAGroupLayerView.m in Sources */ = {isa = PBXBuildFile; fileRef = 620CD7E41D38180800055AD1 /* LAGroupLayerView.m */; };
62FE408D1D3EC81C00CA389D /* CAAnimationGroup+LAAnimatableGroup.m in Sources */ = {isa = PBXBuildFile; fileRef = 62FE408C1D3EC81C00CA389D /* CAAnimationGroup+LAAnimatableGroup.m */; };
@@ -90,6 +89,11 @@
62FE41C21D46886600CA389D /* goftldalt.json in Resources */ = {isa = PBXBuildFile; fileRef = 62FE41BE1D46886600CA389D /* goftldalt.json */; };
62FE41C31D46886600CA389D /* govtid.json in Resources */ = {isa = PBXBuildFile; fileRef = 62FE41BF1D46886600CA389D /* govtid.json */; };
62FE41C41D46886600CA389D /* selfie.json in Resources */ = {isa = PBXBuildFile; fileRef = 62FE41C01D46886600CA389D /* selfie.json */; };
62FE41C61D46D5C900CA389D /* masktest.json in Resources */ = {isa = PBXBuildFile; fileRef = 62FE41C51D46D5C900CA389D /* masktest.json */; };
62FE41C81D47D92E00CA389D /* masksAndSolids.json in Resources */ = {isa = PBXBuildFile; fileRef = 62FE41C71D47D92E00CA389D /* masksAndSolids.json */; };
62FE41CB1D48004A00CA389D /* LAEllipseShapeLayer.m in Sources */ = {isa = PBXBuildFile; fileRef = 62FE41CA1D48004A00CA389D /* LAEllipseShapeLayer.m */; };
62FE41CD1D4804E400CA389D /* circleTest.json in Resources */ = {isa = PBXBuildFile; fileRef = 62FE41CC1D4804E400CA389D /* circleTest.json */; };
62FE41D31D4829E100CA389D /* LAShapeTrimPath.m in Sources */ = {isa = PBXBuildFile; fileRef = 62FE41D21D4829E100CA389D /* LAShapeTrimPath.m */; };
F5B4E946F7B28B4594824641 /* libPods-LotteAnimator.a in Frameworks */ = {isa = PBXBuildFile; fileRef = BC68632413866F85CEACB7EA /* libPods-LotteAnimator.a */; };
/* End PBXBuildFile section */
@@ -150,8 +154,6 @@
620A56611D1C81850030EBFB /* LAAnimatableNumberValue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LAAnimatableNumberValue.m; sourceTree = "<group>"; };
620A56631D1C81930030EBFB /* LAAnimatableShapeValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LAAnimatableShapeValue.h; sourceTree = "<group>"; };
620A56641D1C81930030EBFB /* LAAnimatableShapeValue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LAAnimatableShapeValue.m; sourceTree = "<group>"; };
620CD7CB1D3415F000055AD1 /* LAAnimatableRectValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LAAnimatableRectValue.h; sourceTree = "<group>"; };
620CD7CC1D3415F000055AD1 /* LAAnimatableRectValue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LAAnimatableRectValue.m; sourceTree = "<group>"; };
620CD7CE1D343A2500055AD1 /* LAAnimatableScaleValue.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LAAnimatableScaleValue.h; sourceTree = "<group>"; };
620CD7CF1D343A2500055AD1 /* LAAnimatableScaleValue.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LAAnimatableScaleValue.m; sourceTree = "<group>"; };
620CD7E31D38180800055AD1 /* LAGroupLayerView.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LAGroupLayerView.h; sourceTree = "<group>"; };
@@ -214,6 +216,13 @@
62FE41BE1D46886600CA389D /* goftldalt.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = goftldalt.json; sourceTree = "<group>"; };
62FE41BF1D46886600CA389D /* govtid.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = govtid.json; sourceTree = "<group>"; };
62FE41C01D46886600CA389D /* selfie.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = selfie.json; sourceTree = "<group>"; };
62FE41C51D46D5C900CA389D /* masktest.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = masktest.json; sourceTree = "<group>"; };
62FE41C71D47D92E00CA389D /* masksAndSolids.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = masksAndSolids.json; sourceTree = "<group>"; };
62FE41C91D48004A00CA389D /* LAEllipseShapeLayer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LAEllipseShapeLayer.h; sourceTree = "<group>"; };
62FE41CA1D48004A00CA389D /* LAEllipseShapeLayer.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LAEllipseShapeLayer.m; sourceTree = "<group>"; };
62FE41CC1D4804E400CA389D /* circleTest.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = circleTest.json; sourceTree = "<group>"; };
62FE41D11D4829E100CA389D /* LAShapeTrimPath.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = LAShapeTrimPath.h; sourceTree = "<group>"; };
62FE41D21D4829E100CA389D /* LAShapeTrimPath.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = LAShapeTrimPath.m; sourceTree = "<group>"; };
AEE1A33E4CE2F6024DE7793E /* Pods-LotteAnimator.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-LotteAnimator.debug.xcconfig"; path = "Pods/Target Support Files/Pods-LotteAnimator/Pods-LotteAnimator.debug.xcconfig"; sourceTree = "<group>"; };
BC68632413866F85CEACB7EA /* libPods-LotteAnimator.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-LotteAnimator.a"; sourceTree = BUILT_PRODUCTS_DIR; };
/* End PBXFileReference section */
@@ -277,6 +286,8 @@
486BE04D1D36F1BE00CD14A0 /* LAShapeLayerView.m */,
62FE40E61D3FFBB400CA389D /* LARectShapeLayer.h */,
62FE40E71D3FFBB400CA389D /* LARectShapeLayer.m */,
62FE41C91D48004A00CA389D /* LAEllipseShapeLayer.h */,
62FE41CA1D48004A00CA389D /* LAEllipseShapeLayer.m */,
4804B2FD1C1F55E600DA8AF7 /* ViewController.h */,
4804B2FE1C1F55E600DA8AF7 /* ViewController.m */,
48372A621C20A91C00AD0293 /* LAJSONExplorerViewController.h */,
@@ -315,6 +326,8 @@
48372A4E1C1F99C600AD0293 /* LAShapeGroup.m */,
48372A561C209A6C00AD0293 /* LAShapeStroke.h */,
48372A571C209A6C00AD0293 /* LAShapeStroke.m */,
62FE41D11D4829E100CA389D /* LAShapeTrimPath.h */,
62FE41D21D4829E100CA389D /* LAShapeTrimPath.m */,
48372A591C209A7A00AD0293 /* LAShapeFill.h */,
48372A5A1C209A7A00AD0293 /* LAShapeFill.m */,
48372A5C1C209A8900AD0293 /* LAShapeTransform.h */,
@@ -345,6 +358,9 @@
48372A651C20B04300AD0293 /* JSONExamples */ = {
isa = PBXGroup;
children = (
62FE41CC1D4804E400CA389D /* circleTest.json */,
62FE41C71D47D92E00CA389D /* masksAndSolids.json */,
62FE41C51D46D5C900CA389D /* masktest.json */,
62FE41BD1D46886600CA389D /* allset.json */,
62FE41BE1D46886600CA389D /* goftldalt.json */,
62FE41BF1D46886600CA389D /* govtid.json */,
@@ -413,8 +429,6 @@
62FE40E41D3FF78800CA389D /* LAAnimatableBoundsValue.m */,
620CD7CE1D343A2500055AD1 /* LAAnimatableScaleValue.h */,
620CD7CF1D343A2500055AD1 /* LAAnimatableScaleValue.m */,
620CD7CB1D3415F000055AD1 /* LAAnimatableRectValue.h */,
620CD7CC1D3415F000055AD1 /* LAAnimatableRectValue.m */,
62FE408B1D3EC81C00CA389D /* CAAnimationGroup+LAAnimatableGroup.h */,
62FE408C1D3EC81C00CA389D /* CAAnimationGroup+LAAnimatableGroup.m */,
);
@@ -505,6 +519,7 @@
4804B3041C1F55E600DA8AF7 /* Assets.xcassets in Resources */,
62FE40D11D3EDC7400CA389D /* 062_AnimateTransformParented.json in Resources */,
62FE40D71D3EDC7400CA389D /* 100_House_AnimateInAndOut.json in Resources */,
62FE41CD1D4804E400CA389D /* circleTest.json in Resources */,
62FE40D41D3EDC7400CA389D /* 071_AnimatePathShape.json in Resources */,
62FE40CE1D3EDC7400CA389D /* 058_AnimateTransformPositionHoldKeyframe.json in Resources */,
62FE40CC1D3EDC7400CA389D /* 056_AnimateTransformPositionCustomEaseIn.json in Resources */,
@@ -522,6 +537,7 @@
62FE40CA1D3EDC7400CA389D /* 054_AnimateTransformPositionEaseOut.json in Resources */,
62FE40B51D3EDC7400CA389D /* 002_ShapeLayerLine_01.json in Resources */,
62FE40DD1D3FF0D900CA389D /* Heart58OnOff.json in Resources */,
62FE41C81D47D92E00CA389D /* masksAndSolids.json in Resources */,
62FE40B81D3EDC7400CA389D /* 005_TwoShapeLayerSquaresDifferent_01.json in Resources */,
62FE40C01D3EDC7400CA389D /* 013_ShapeMasked_01.json in Resources */,
486BE04B1D36E06C00CD14A0 /* newMoovin.json in Resources */,
@@ -539,6 +555,7 @@
62FE40EA1D401C0700CA389D /* scaleTest.json in Resources */,
62FE40BE1D3EDC7400CA389D /* 011_MergePaths_01.json in Resources */,
62FE40BC1D3EDC7400CA389D /* 009_ShapeLayerRepeater_01.json in Resources */,
62FE41C61D46D5C900CA389D /* masktest.json in Resources */,
62FE40C21D3EDC7400CA389D /* 015_DottedLine_01.json in Resources */,
62FE40CD1D3EDC7400CA389D /* 057_AnimateTransformPositionCustomEaseInout.json in Resources */,
);
@@ -602,9 +619,11 @@
4804B31E1C1F757600DA8AF7 /* UIColor+Expanded.m in Sources */,
4804B2FF1C1F55E600DA8AF7 /* ViewController.m in Sources */,
48372A641C20A91C00AD0293 /* LAJSONExplorerViewController.m in Sources */,
62FE41D31D4829E100CA389D /* LAShapeTrimPath.m in Sources */,
62FE41431D41862200CA389D /* LAAnimatableLayer.m in Sources */,
620A56651D1C81930030EBFB /* LAAnimatableShapeValue.m in Sources */,
4804B3191C1F6DEA00DA8AF7 /* LAComposition.m in Sources */,
62FE41CB1D48004A00CA389D /* LAEllipseShapeLayer.m in Sources */,
4804B2FC1C1F55E600DA8AF7 /* AppDelegate.m in Sources */,
4804B3211C1F761800DA8AF7 /* BWMath.m in Sources */,
62FE40E51D3FF78800CA389D /* LAAnimatableBoundsValue.m in Sources */,
@@ -626,7 +645,6 @@
48372A551C209A5F00AD0293 /* LAShapePath.m in Sources */,
620CD7E51D38180800055AD1 /* LAGroupLayerView.m in Sources */,
48372AB71C20D97200AD0293 /* LAShapeCircle.m in Sources */,
620CD7CD1D3415F000055AD1 /* LAAnimatableRectValue.m in Sources */,
620A565C1D1C81610030EBFB /* LAAnimatableColorValue.m in Sources */,
48372A5E1C209A8900AD0293 /* LAShapeTransform.m in Sources */,
62FE41BC1D42DD8500CA389D /* LAMaskLayer.m in Sources */,

View File

@@ -67,13 +67,13 @@
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "LotteAnimator/LAShapeCircle.m"
timestampString = "490729764.635343"
filePath = "LotteAnimator/LAMaskLayer.m"
timestampString = "491264085.840767"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "14"
endingLineNumber = "14"
landmarkName = "-initWithJSON:frameRate:"
startingLineNumber = "54"
endingLineNumber = "54"
landmarkName = "-renderInContext:"
landmarkType = "5">
</BreakpointContent>
</BreakpointProxy>
@@ -83,13 +83,13 @@
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "LotteAnimator/LAAnimatableScaleValue.m"
timestampString = "490740783.490737"
filePath = "LotteAnimator/LAMaskLayer.m"
timestampString = "491264087.213296"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "82"
endingLineNumber = "82"
landmarkName = "-_buildAnimationForKeyframes:"
startingLineNumber = "50"
endingLineNumber = "50"
landmarkName = "-drawInContext:"
landmarkType = "5">
</BreakpointContent>
</BreakpointProxy>
@@ -100,7 +100,7 @@
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "LotteAnimator/LAAnimatableLayer.m"
timestampString = "490920717.958644"
timestampString = "491266116.833188"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "56"
@@ -109,53 +109,5 @@
landmarkType = "5">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "LotteAnimator/LALayerView.m"
timestampString = "490921111.145475"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "128"
endingLineNumber = "128"
landmarkName = "-_setupViewFromModel"
landmarkType = "5">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "LotteAnimator/CAAnimationGroup+LAAnimatableGroup.m"
timestampString = "490920346.033008"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "14"
endingLineNumber = "14"
landmarkName = "+animationGroupForAnimatablePropertiesWithKeyPaths:"
landmarkType = "5">
</BreakpointContent>
</BreakpointProxy>
<BreakpointProxy
BreakpointExtensionID = "Xcode.Breakpoint.FileBreakpoint">
<BreakpointContent
shouldBeEnabled = "Yes"
ignoreCount = "0"
continueAfterRunningActions = "No"
filePath = "LotteAnimator/CAAnimationGroup+LAAnimatableGroup.m"
timestampString = "490920366.856974"
startingColumnNumber = "9223372036854775807"
endingColumnNumber = "9223372036854775807"
startingLineNumber = "29"
endingLineNumber = "29"
landmarkName = "+animationGroupForAnimatablePropertiesWithKeyPaths:"
landmarkType = "5">
</BreakpointContent>
</BreakpointProxy>
</Breakpoints>
</Bucket>

View File

@@ -93,5 +93,4 @@
layer.beginTime = [layer convertTime:CACurrentMediaTime() fromLayer:nil];
}
@end

View File

@@ -1,28 +0,0 @@
//
// LAAnimatableSizeValue.h
// LotteAnimator
//
// Created by brandon_withrow on 7/11/16.
// Copyright © 2016 Brandon Withrow. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface LAAnimatableRectValue : NSObject
- (instancetype)initWithRectValues:(NSDictionary *)rectValues frameRate:(NSNumber *)frameRate;
@property (nonatomic, readonly) CGRect initialRect;
@property (nonatomic, readonly) NSArray *rectKeyframes;
@property (nonatomic, readonly) NSArray<NSNumber *> *keyTimes;
@property (nonatomic, readonly) NSArray<CAMediaTimingFunction *> *timingFunctions;
@property (nonatomic, readonly) NSTimeInterval delay;
@property (nonatomic, readonly) NSTimeInterval duration;
@property (nonatomic, readonly) BOOL hasAnimation;
@property (nonatomic, readonly) NSNumber *startFrame;
@property (nonatomic, readonly) NSNumber *durationFrames;
@property (nonatomic, readonly) NSNumber *frameRate;
- (CAKeyframeAnimation *)animationForKeyPath:(NSString *)keypath;
@end

View File

@@ -1,22 +0,0 @@
//
// LAAnimatableSizeValue.m
// LotteAnimator
//
// Created by brandon_withrow on 7/11/16.
// Copyright © 2016 Brandon Withrow. All rights reserved.
//
#import "LAAnimatableRectValue.h"
@implementation LAAnimatableRectValue
- (instancetype)initWithRectValues:(NSDictionary *)rectValues frameRate:(NSNumber *)frameRate {
self = [super init];
if (self) {
_frameRate = frameRate;
}
return self;
}
@end

View File

@@ -28,11 +28,20 @@
NSMutableDictionary *layerMap = [NSMutableDictionary dictionary];
NSArray *reversedItems = [[_sceneModel.layers reverseObjectEnumerator] allObjects];
LALayerView *maskedLayer = nil;
for (LALayer *layer in reversedItems) {
LALayerView *layerView = [[LALayerView alloc] initWithModel:layer inComposition:_sceneModel];
layerMap[layer.layerID] = layerView;
[self.layer addSublayer:layerView];
if (maskedLayer) {
maskedLayer.mask = layerView;
maskedLayer = nil;
} else {
if (layer.matteType == LAMatteTypeAdd) {
maskedLayer = layerView;
}
[self.layer addSublayer:layerView];
}
}
_layerMap = layerMap;
}

View File

@@ -0,0 +1,20 @@
//
// LAEllipseShapeLayer.h
// LotteAnimator
//
// Created by brandon_withrow on 7/26/16.
// Copyright © 2016 Brandon Withrow. All rights reserved.
//
#import "LAAnimatableLayer.h"
@interface LAEllipseShapeLayer : LAAnimatableLayer
- (instancetype)initWithEllipseShape:(LAShapeCircle *)circleShape
fill:(LAShapeFill *)fill
stroke:(LAShapeStroke *)stroke
trim:(LAShapeTrimPath *)trim
transform:(LAShapeTransform *)transform
withDuration:(NSTimeInterval)duration;
@end

View File

@@ -0,0 +1,121 @@
//
// LAEllipseShapeLayer.m
// LotteAnimator
//
// Created by brandon_withrow on 7/26/16.
// Copyright © 2016 Brandon Withrow. All rights reserved.
//
#import "LAEllipseShapeLayer.h"
#import "CAAnimationGroup+LAAnimatableGroup.h"
@implementation LAEllipseShapeLayer {
LAShapeTransform *_transform;
LAShapeStroke *_stroke;
LAShapeFill *_fill;
LAShapeCircle *_circle;
LAShapeTrimPath *_trim;
CAShapeLayer *_fillLayer;
CAShapeLayer *_strokeLayer;
CAAnimationGroup *_animation;
CAAnimationGroup *_strokeAnimation;
CAAnimationGroup *_fillAnimation;
}
- (instancetype)initWithEllipseShape:(LAShapeCircle *)circleShape
fill:(LAShapeFill *)fill
stroke:(LAShapeStroke *)stroke
trim:(LAShapeTrimPath *)trim
transform:(LAShapeTransform *)transform
withDuration:(NSTimeInterval)duration {
self = [super initWithDuration:duration];
if (self) {
_circle = circleShape;
_stroke = stroke;
_fill = fill;
_transform = transform;
_trim = trim;
self.allowsEdgeAntialiasing = YES;
self.frame = _transform.compBounds;
self.anchorPoint = _transform.anchor.initialPoint;
self.opacity = _transform.opacity.initialValue.floatValue;
self.position = _transform.position.initialPoint;
self.transform = _transform.scale.initialScale;
self.sublayerTransform = CATransform3DMakeRotation(_transform.rotation.initialValue.floatValue, 0, 0, 1);
if (fill) {
_fillLayer = [CAShapeLayer new];
_fillLayer.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-50, -50, 100, 100)].CGPath;
_fillLayer.allowsEdgeAntialiasing = YES;
_fillLayer.position = circleShape.position.initialPoint;
_fillLayer.transform = circleShape.scale.initialScale;
_fillLayer.fillColor = _fill.color.initialColor.CGColor;
_fillLayer.opacity = _fill.opacity.initialValue.floatValue;
[self addSublayer:_fillLayer];
}
if (stroke) {
_strokeLayer = [CAShapeLayer new];
_strokeLayer.path = [UIBezierPath bezierPathWithOvalInRect:CGRectMake(-50, -50, 100, 100)].CGPath;
_strokeLayer.allowsEdgeAntialiasing = YES;
_strokeLayer.position = circleShape.position.initialPoint;
_strokeLayer.transform = circleShape.scale.initialScale;
_strokeLayer.strokeColor = _stroke.color.initialColor.CGColor;
_strokeLayer.opacity = _stroke.opacity.initialValue.floatValue;
_strokeLayer.lineWidth = _stroke.width.initialValue.floatValue;
_strokeLayer.fillColor = nil;
_strokeLayer.backgroundColor = nil;
_strokeLayer.lineDashPattern = _stroke.lineDashPattern;
if (trim) {
_strokeLayer.strokeStart = _trim.start.initialValue.floatValue;
_strokeLayer.strokeEnd = _trim.end.initialValue.floatValue;
}
[self addSublayer:_strokeLayer];
}
self.animationSublayers = [NSArray arrayWithArray:self.sublayers];
[self _buildAnimation];
[self pause];
}
return self;
}
- (void)_buildAnimation {
if (_transform) {
_animation = [CAAnimationGroup animationGroupForAnimatablePropertiesWithKeyPaths:@{@"opacity" : _transform.opacity,
@"position" : _transform.position,
@"anchorPoint" : _transform.anchor,
@"transform" : _transform.scale,
@"sublayerTransform.rotation" : _transform.rotation}];
[self addAnimation:_animation forKey:@"LotteAnimation"];
}
if (_stroke) {
NSMutableDictionary *properties = [NSMutableDictionary dictionaryWithDictionary:@{@"strokeColor" : _stroke.color,
@"opacity" : _stroke.opacity,
@"lineWidth" : _stroke.width,
@"position" : _circle.position,
@"transform" : _circle.scale}];
if (_trim) {
properties[@"strokeStart"] = _trim.start;
properties[@"strokeEnd"] = _trim.end;
}
_strokeAnimation = [CAAnimationGroup animationGroupForAnimatablePropertiesWithKeyPaths:properties];
[_strokeLayer addAnimation:_strokeAnimation forKey:@""];
}
if (_fill) {
_fillAnimation = [CAAnimationGroup animationGroupForAnimatablePropertiesWithKeyPaths:@{@"backgroundColor" : _fill.color,
@"opacity" : _fill.opacity,
@"position" : _circle.position,
@"transform" : _circle.scale}];
[_fillLayer addAnimation:_fillAnimation forKey:@""];
}
}
@end

View File

@@ -9,6 +9,8 @@
#import "LAGroupLayerView.h"
#import "LAShapeLayerView.h"
#import "LARectShapeLayer.h"
#import "LAEllipseShapeLayer.h"
#import "CAAnimationGroup+LAAnimatableGroup.h"
@implementation LAGroupLayerView {
@@ -45,6 +47,7 @@
LAShapeFill *currentFill;
LAShapeStroke *currentStroke;
LAShapeTransform *currentTransform;
LAShapeTrimPath *currentTrim;
NSMutableArray *shapeLayers = [NSMutableArray array];
NSMutableArray *groupLayers = [NSMutableArray array];
@@ -56,11 +59,14 @@
currentStroke = item;
} else if ([item isKindOfClass:[LAShapeFill class]]) {
currentFill = item;
} else if ([item isKindOfClass:[LAShapeTrimPath class]]) {
currentTrim = item;
} else if ([item isKindOfClass:[LAShapePath class]]) {
LAShapePath *shapePath = (LAShapePath *)item;
LAShapeLayerView *shapeLayer = [[LAShapeLayerView alloc] initWithShape:shapePath
fill:currentFill
stroke:currentStroke
trim:currentTrim
transform:currentTransform
withDuration:self.laAnimationDuration];
[shapeLayers addObject:shapeLayer];
@@ -74,6 +80,16 @@
withDuration:self.laAnimationDuration];
[shapeLayers addObject:shapeLayer];
[self addSublayer:shapeLayer];
} else if ([item isKindOfClass:[LAShapeCircle class]]) {
LAShapeCircle *shapeCircle = (LAShapeCircle *)item;
LAEllipseShapeLayer *shapeLayer = [[LAEllipseShapeLayer alloc] initWithEllipseShape:shapeCircle
fill:currentFill
stroke:currentStroke
trim:currentTrim
transform:currentTransform
withDuration:self.laAnimationDuration];
[shapeLayers addObject:shapeLayer];
[self addSublayer:shapeLayer];
} else if ([item isKindOfClass:[LAShapeGroup class]]) {
LAShapeGroup *shapeGroup = (LAShapeGroup *)item;
LAGroupLayerView *groupLayer = [[LAGroupLayerView alloc] initWithShapeGroup:shapeGroup

View File

@@ -14,7 +14,6 @@
@class LAAnimatableColorValue;
@class LAAnimatablePointValue;
@class LAAnimatableNumberValue;
@class LAAnimatableRectValue;
@class LAAnimatableScaleValue;
@class LAComposition;
@@ -26,6 +25,13 @@ typedef enum : NSInteger {
LALayerTypeShape
} LALayerType;
typedef enum : NSInteger {
LAMatteTypeNone,
LAMatteTypeAdd,
LAMatteTypeInvert,
LALayerTypeUknown
} LAMatteType;
@interface LALayer : NSObject
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary fromComposition:(LAComposition *)composition;
@@ -42,8 +48,9 @@ typedef enum : NSInteger {
@property (nonatomic, readonly) NSArray<LAShapeGroup *> *shapes;
@property (nonatomic, readonly) NSArray<LAMask *> *masks;
@property (nonatomic, readonly) LAAnimatableRectValue *solidBounds;
@property (nonatomic, readonly) LAAnimatableColorValue *solidColor;
@property (nonatomic, readonly) NSNumber *solidWidth;
@property (nonatomic, readonly) NSNumber *solidHeight;
@property (nonatomic, readonly) UIColor *solidColor;
@property (nonatomic, readonly) LAAnimatableNumberValue *opacity;
@property (nonatomic, readonly) LAAnimatableNumberValue *rotation;
@@ -59,4 +66,6 @@ typedef enum : NSInteger {
@property (nonatomic, readonly) NSArray *inOutKeyTimes;
@property (nonatomic, readonly) NSTimeInterval compDuration;
@property (nonatomic, readonly) LAMatteType matteType;
@end

View File

@@ -42,8 +42,10 @@
_outFrame = [jsonDictionary[@"op"] copy];
if (_layerType == LALayerTypeSolid) {
// TODO Solids.
_solidWidth = jsonDictionary[@"sw"];
_solidHeight = jsonDictionary[@"sh"];
NSString *solidColor = jsonDictionary[@"sc"];
_solidColor = [UIColor colorWithHexString:solidColor];
}
NSDictionary *ks = jsonDictionary[@"ks"];
@@ -78,6 +80,9 @@
_scale = [[LAAnimatableScaleValue alloc] initWithScaleValues:scale frameRate:_framerate];
}
_matteType = [jsonDictionary[@"tt"] integerValue];
NSMutableArray *masks = [NSMutableArray array];
for (NSDictionary *maskJSON in jsonDictionary[@"masksProperties"]) {
LAMask *mask = [[LAMask alloc] initWithJSON:maskJSON frameRate:_framerate];

View File

@@ -10,6 +10,7 @@
#import "LAShapeLayerView.h"
#import "LAGroupLayerView.h"
#import "CAAnimationGroup+LAAnimatableGroup.h"
#import "LAMaskLayer.h"
@interface LAParentLayer : LAAnimatableLayer
@@ -59,7 +60,7 @@
CAKeyframeAnimation *_inOutAnimation;
NSArray<LAParentLayer *> *_parentLayers;
LAComposition *_composition;
LAMaskLayer *_maskLayer;
}
- (instancetype)initWithModel:(LALayer *)model inComposition:(LAComposition *)comp {
@@ -73,9 +74,18 @@
}
- (void)_setupViewFromModel {
self.bounds = _composition.compBounds;
self.backgroundColor = nil;
if (_layerModel.layerType == LALayerTypeSolid) {
self.bounds = CGRectMake(0, 0, _layerModel.solidWidth.floatValue, _layerModel.solidHeight.floatValue);
} else {
self.bounds = _composition.compBounds;
}
self.anchorPoint = CGPointZero;
_childContainerLayer = [CALayer new];
_childContainerLayer.bounds = self.bounds;
_childContainerLayer.backgroundColor = _layerModel.solidColor.CGColor;
self.animationSublayers = @[_childContainerLayer];
NSNumber *parentID = _layerModel.parentID;
@@ -121,9 +131,29 @@
_shapeLayers = shapeLayers;
// CALayer *anchorLayer = [CALayer new];
// anchorLayer.bounds = CGRectMake(0, 0, 20, 20);
// anchorLayer.backgroundColor = [UIColor redColor].CGColor;
// anchorLayer.anchorPoint = CGPointMake(0.5, 0.5);
// anchorLayer.position = CGPointZero;
// anchorLayer.opacity = 0.25;
// _childContainerLayer.borderWidth = 6;
// _childContainerLayer.backgroundColor = [UIColor greenColor].CGColor;
// _childContainerLayer.borderColor = [UIColor redColor].CGColor;
// [_childContainerLayer addSublayer:anchorLayer];
if (_layerModel.masks) {
_maskLayer = [[LAMaskLayer alloc] initWithMasks:_layerModel.masks inComposition:_composition];
_maskLayer.opacity = 0.5;
[_childContainerLayer addSublayer:_maskLayer];
}
NSMutableArray *childLayers = [NSMutableArray array];
[childLayers addObjectsFromArray:_parentLayers];
[childLayers addObjectsFromArray:_shapeLayers];
if (_maskLayer) {
[childLayers addObject:_maskLayer];
}
self.childLayers = childLayers;
[self _buildAnimations];

View File

@@ -7,14 +7,17 @@
//
#import "LAMaskLayer.h"
#import "CAAnimationGroup+LAAnimatableGroup.h"
@implementation LAMaskLayer {
LAComposition *_composition;
NSArray *_maskLayers;
}
- (instancetype)initWithMasks:(NSArray<LAMask *> *)masks inComposition:(LAComposition *)comp {
self = [super initWithDuration:comp.timeDuration];
if (self) {
// self.bounds = comp.compBounds;
_masks = masks;
_composition = comp;
[self _setupViewFromModel];
@@ -23,6 +26,31 @@
}
- (void)_setupViewFromModel {
NSMutableArray *maskLayers = [NSMutableArray array];
for (LAMask *mask in _masks) {
CAShapeLayer *maskLayer = [CAShapeLayer new];
maskLayer.path = mask.maskPath.initialShape.CGPath;
maskLayer.fillColor = [UIColor whiteColor].CGColor;
maskLayer.opacity = mask.opacity.initialValue.floatValue;
[self addSublayer:maskLayer];
CAAnimationGroup *animGroup = [CAAnimationGroup animationGroupForAnimatablePropertiesWithKeyPaths:@{@"opacity" : mask.opacity,
@"path" : mask.maskPath}];
if (animGroup) {
[maskLayer addAnimation:animGroup forKey:@""];
}
[maskLayers addObject:maskLayer];
}
_maskLayers = maskLayers;
self.animationSublayers = maskLayers;
[self pause];
}
- (void)drawInContext:(CGContextRef)ctx {
}
-(void)renderInContext:(CGContextRef)ctx {
}

View File

@@ -22,9 +22,9 @@
#import "LAAnimatableColorValue.h"
#import "LAAnimatableNumberValue.h"
#import "LAAnimatablePointValue.h"
#import "LAAnimatableRectValue.h"
#import "LAAnimatableScaleValue.h"
#import "LAAnimatableShapeValue.h"
#import "LAShapeTrimPath.h"
#endif /* LAModels_h */

View File

@@ -12,9 +12,9 @@
@interface LARectShapeLayer : LAAnimatableLayer
- (instancetype)initWithRectShape:(LAShapeRectangle *)rectShape
fill:(LAShapeFill *)fill
stroke:(LAShapeStroke *)stroke
transform:(LAShapeTransform *)transform
fill:(LAShapeFill *)fill
stroke:(LAShapeStroke *)stroke
transform:(LAShapeTransform *)transform
withDuration:(NSTimeInterval)duration;
@end

View File

@@ -43,24 +43,30 @@
self.transform = _transform.scale.initialScale;
self.sublayerTransform = CATransform3DMakeRotation(_transform.rotation.initialValue.floatValue, 0, 0, 1);
_fillLayer = [CALayer layer];
_fillLayer.allowsEdgeAntialiasing = YES;
_fillLayer.bounds = rectShape.bounds.initialBounds;
_fillLayer.position = rectShape.position.initialPoint;
_fillLayer.cornerRadius = rectShape.cornerRadius.initialValue.floatValue;
_fillLayer.backgroundColor = _fill.color.initialColor.CGColor;
_fillLayer.opacity = _fill.opacity.initialValue.floatValue;
[self addSublayer:_fillLayer];
if (fill) {
_fillLayer = [CALayer layer];
_fillLayer.allowsEdgeAntialiasing = YES;
_fillLayer.bounds = rectShape.bounds.initialBounds;
_fillLayer.position = rectShape.position.initialPoint;
_fillLayer.cornerRadius = rectShape.cornerRadius.initialValue.floatValue;
_fillLayer.backgroundColor = _fill.color.initialColor.CGColor;
_fillLayer.opacity = _fill.opacity.initialValue.floatValue;
[self addSublayer:_fillLayer];
}
if (stroke) {
_strokeLayer = [CALayer layer];
_strokeLayer.allowsEdgeAntialiasing = YES;
_strokeLayer.bounds = rectShape.bounds.initialBounds;
_strokeLayer.position = rectShape.position.initialPoint;
_strokeLayer.cornerRadius = rectShape.cornerRadius.initialValue.floatValue;
_strokeLayer.borderColor = _stroke.color.initialColor.CGColor;
_strokeLayer.opacity = _stroke.opacity.initialValue.floatValue;
_strokeLayer.borderWidth = _stroke.width.initialValue.floatValue;
_strokeLayer.backgroundColor = nil;
}
self.animationSublayers = [NSArray arrayWithArray:self.sublayers];
_strokeLayer = [CALayer layer];
_strokeLayer.allowsEdgeAntialiasing = YES;
_strokeLayer.bounds = rectShape.bounds.initialBounds;
_strokeLayer.position = rectShape.position.initialPoint;
_strokeLayer.cornerRadius = rectShape.cornerRadius.initialValue.floatValue;
_strokeLayer.borderColor = _stroke.color.initialColor.CGColor;
_strokeLayer.opacity = _stroke.opacity.initialValue.floatValue;
_strokeLayer.borderWidth = _stroke.width.initialValue.floatValue;
_strokeLayer.backgroundColor = nil;
[self addSublayer:_strokeLayer];
[self _buildAnimation];
[self pause];

View File

@@ -12,4 +12,7 @@
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary frameRate:(NSNumber *)frameRate;
@property (nonatomic, readonly) LAAnimatablePointValue *position;
@property (nonatomic, readonly) LAAnimatableScaleValue *scale;
@end

View File

@@ -19,7 +19,16 @@
}
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary frameRate:(NSNumber *)frameRate {
NSDictionary *position = jsonDictionary[@"p"];
if (position) {
_position = [[LAAnimatablePointValue alloc] initWithPointValues:position frameRate:frameRate];
_position.usePathAnimation = NO;
}
NSDictionary *scale = jsonDictionary[@"s"];
if (scale) {
_scale = [[LAAnimatableScaleValue alloc] initWithScaleValues:scale frameRate:frameRate];
}
}
@end

View File

@@ -13,6 +13,7 @@
#import "LAShapeStroke.h"
#import "LAShapeTransform.h"
#import "LAShapeRectangle.h"
#import "LAShapeTrimPath.h"
@implementation LAShapeGroup
@@ -51,6 +52,9 @@
} else if ([type isEqualToString:@"rc"]) {
LAShapeRectangle *rectangle = [[LAShapeRectangle alloc] initWithJSON:itemJSON frameRate:frameRate];
[items addObject:rectangle];
} else if ([type isEqualToString:@"tm"]) {
LAShapeTrimPath *trim = [[LAShapeTrimPath alloc] initWithJSON:itemJSON frameRate:frameRate];
[items addObject:trim];
}
}
_items = items;

View File

@@ -14,9 +14,8 @@
- (instancetype)initWithShape:(LAShapePath *)shape
fill:(LAShapeFill *)fill
stroke:(LAShapeStroke *)stroke
trim:(LAShapeTrimPath *)trim
transform:(LAShapeTransform *)transform
withDuration:(NSTimeInterval)duration;
- (void)startAnimation;
@end

View File

@@ -14,6 +14,7 @@
LAShapeStroke *_stroke;
LAShapeFill *_fill;
LAShapePath *_path;
LAShapeTrimPath *_trim;
CAShapeLayer *_fillLayer;
CAShapeLayer *_strokeLayer;
@@ -26,6 +27,7 @@
- (instancetype)initWithShape:(LAShapePath *)shape
fill:(LAShapeFill *)fill
stroke:(LAShapeStroke *)stroke
trim:(LAShapeTrimPath *)trim
transform:(LAShapeTransform *)transform
withDuration:(NSTimeInterval)duration {
self = [super initWithDuration:duration];
@@ -34,6 +36,7 @@
_stroke = stroke;
_fill = fill;
_transform = transform;
_trim = trim;
self.allowsEdgeAntialiasing = YES;
self.frame = _transform.compBounds;
@@ -43,26 +46,43 @@
self.transform = _transform.scale.initialScale;
self.sublayerTransform = CATransform3DMakeRotation(_transform.rotation.initialValue.floatValue, 0, 0, 1);
_fillLayer = [CAShapeLayer layer];
_fillLayer.allowsEdgeAntialiasing = YES;
_fillLayer.path = _path.shapePath.initialShape.CGPath;
_fillLayer.fillColor = _fill.color.initialColor.CGColor;
_fillLayer.opacity = _fill.opacity.initialValue.floatValue;
[self addSublayer:_fillLayer];
if (fill) {
_fillLayer = [CAShapeLayer layer];
_fillLayer.allowsEdgeAntialiasing = YES;
_fillLayer.path = _path.shapePath.initialShape.CGPath;
_fillLayer.fillColor = _fill.color.initialColor.CGColor;
_fillLayer.opacity = _fill.opacity.initialValue.floatValue;
[self addSublayer:_fillLayer];
}
_strokeLayer = [CAShapeLayer layer];
_strokeLayer.allowsEdgeAntialiasing = YES;
_strokeLayer.path = _path.shapePath.initialShape.CGPath;
_strokeLayer.strokeColor = _stroke.color.initialColor.CGColor;
_strokeLayer.opacity = _stroke.opacity.initialValue.floatValue;
_strokeLayer.lineWidth = _stroke.width.initialValue.floatValue;
_strokeLayer.fillColor = nil;
self.animationSublayers = @[_fillLayer, _strokeLayer];
if (stroke) {
_strokeLayer = [CAShapeLayer layer];
_strokeLayer.allowsEdgeAntialiasing = YES;
_strokeLayer.path = _path.shapePath.initialShape.CGPath;
_strokeLayer.strokeColor = _stroke.color.initialColor.CGColor;
_strokeLayer.opacity = _stroke.opacity.initialValue.floatValue;
_strokeLayer.lineWidth = _stroke.width.initialValue.floatValue;
_strokeLayer.lineDashPattern = _stroke.lineDashPattern;
if (trim) {
_strokeLayer.strokeStart = _trim.start.initialValue.floatValue;
_strokeLayer.strokeEnd = _trim.end.initialValue.floatValue;
}
_strokeLayer.fillColor = nil;
}
self.animationSublayers = [NSArray arrayWithArray:self.sublayers];
[self addSublayer:_strokeLayer];
[self _buildAnimation];
[self pause];
// CALayer *anchorLayer = [CALayer new];
// anchorLayer.bounds = CGRectMake(0, 0, 10, 10);
// anchorLayer.backgroundColor = [UIColor blueColor].CGColor;
// anchorLayer.anchorPoint = CGPointMake(0.5, 0.5);
// anchorLayer.position = CGPointZero;
// self.borderColor = [UIColor blueColor].CGColor;
// self.borderWidth = 2;
// [self addSublayer:anchorLayer];
}
return self;
}
@@ -78,10 +98,15 @@
}
if (_stroke) {
_strokeAnimation = [CAAnimationGroup animationGroupForAnimatablePropertiesWithKeyPaths:@{@"strokeColor" : _stroke.color,
@"opacity" : _stroke.opacity,
@"lineWidth" : _stroke.width,
@"path" : _path.shapePath}];
NSMutableDictionary *properties = [NSMutableDictionary dictionaryWithDictionary:@{@"strokeColor" : _stroke.color,
@"opacity" : _stroke.opacity,
@"lineWidth" : _stroke.width,
@"path" : _path.shapePath}];
if (_trim) {
properties[@"strokeStart"] = _trim.start;
properties[@"strokeEnd"] = _trim.end;
}
_strokeAnimation = [CAAnimationGroup animationGroupForAnimatablePropertiesWithKeyPaths:properties];
[_strokeLayer addAnimation:_strokeAnimation forKey:@""];
}

View File

@@ -19,5 +19,6 @@
@property (nonatomic, readonly) LAAnimatableColorValue *color;
@property (nonatomic, readonly) LAAnimatableNumberValue *opacity;
@property (nonatomic, readonly) LAAnimatableNumberValue *width;
@property (nonatomic, readonly) NSArray *lineDashPattern;
@end

View File

@@ -39,6 +39,20 @@
NSNumber *fillEnabled = jsonDictionary[@"fillEnabled"];
_fillEnabled = fillEnabled.boolValue;
NSArray *dashes = jsonDictionary[@"d"];
if (dashes) {
NSMutableArray *dashPattern = [NSMutableArray array];
for (NSDictionary *dash in dashes) {
if ([dash[@"n"] isEqualToString:@"o"]) {
continue;
}
NSDictionary *value = dash[@"v"];
LAAnimatableNumberValue *numberValue = [[LAAnimatableNumberValue alloc] initWithNumberValues:value frameRate:frameRate];
[dashPattern addObject:[numberValue.initialValue copy]];
}
_lineDashPattern = dashPattern;
}
}
@end

View File

@@ -0,0 +1,19 @@
//
// LAShapeTrimPath.h
// LotteAnimator
//
// Created by brandon_withrow on 7/26/16.
// Copyright © 2016 Brandon Withrow. All rights reserved.
//
#import <Foundation/Foundation.h>
@class LAAnimatableNumberValue;
@interface LAShapeTrimPath : NSObject
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary frameRate:(NSNumber *)frameRate;
@property (nonatomic, readonly) LAAnimatableNumberValue *start;
@property (nonatomic, readonly) LAAnimatableNumberValue *end;
@end

View File

@@ -0,0 +1,35 @@
//
// LAShapeTrimPath.m
// LotteAnimator
//
// Created by brandon_withrow on 7/26/16.
// Copyright © 2016 Brandon Withrow. All rights reserved.
//
#import "LAShapeTrimPath.h"
@implementation LAShapeTrimPath
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary frameRate:(NSNumber *)frameRate {
self = [super init];
if (self) {
[self _mapFromJSON:jsonDictionary frameRate:frameRate];
}
return self;
}
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary frameRate:(NSNumber *)frameRate {
NSDictionary *start = jsonDictionary[@"s"];
if (start) {
_start = [[LAAnimatableNumberValue alloc] initWithNumberValues:start frameRate:frameRate];
[_start remapValuesFromMin:@0 fromMax:@100 toMin:@0 toMax:@1];
}
NSDictionary *end = jsonDictionary[@"e"];
if (end) {
_end = [[LAAnimatableNumberValue alloc] initWithNumberValues:end frameRate:frameRate];
[_end remapValuesFromMin:@0 fromMax:@100 toMin:@0 toMax:@1];
}
}
@end

View File

@@ -359,7 +359,8 @@ static NSMutableDictionary *colorNameCache = nil;
// Returns a UIColor by scanning the string for a hex number and passing that to +[UIColor colorWithRGBHex:]
// Skips any leading whitespace and ignores any trailing characters
+ (UIColor *)colorWithHexString:(NSString *)stringToConvert {
NSScanner *scanner = [NSScanner scannerWithString:stringToConvert];
NSString *strippedString = [stringToConvert stringByReplacingOccurrencesOfString:@"#" withString:@""];
NSScanner *scanner = [NSScanner scannerWithString:strippedString];
unsigned hexNum;
if (![scanner scanHexInt:&hexNum]) return nil;
return [UIColor colorWithRGBHex:hexNum];

View File

@@ -0,0 +1 @@
{"assets":[],"v":"4.1.7","ddd":0,"layers":[{"ddd":0,"ind":0,"ty":4,"nm":"Shape Layer 2","ks":{"o":{"k":100},"r":{"k":0},"p":{"k":[300,300,0]},"a":{"k":[0,0,0]},"s":{"k":[100,247.571,100]}},"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"k":[{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":0,"s":[140.039,147.461],"e":[28.039,29.525],"__fnct":[null,null]},{"t":98}]},"p":{"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[0,0],"e":[-87,69],"to":[-14.5,11.5],"ti":[14.5,-11.5]},{"t":98}]},"nm":"Ellipse Path 1","closed":true},{"d":1,"ty":"el","s":{"k":[{"i":{"x":[0.833,0.833],"y":[0.833,0.833]},"o":{"x":[0.167,0.167],"y":[0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":0,"s":[140.039,147.461],"e":[28.039,29.525],"__fnct":[null,null]},{"t":98}]},"p":{"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[0,0],"e":[-87,69],"to":[-14.5,11.5],"ti":[14.5,-11.5]},{"t":98}]},"nm":"Ellipse Path 1","closed":true},{"ty":"st","fillEnabled":true,"c":{"k":[255,255,255,255]},"o":{"k":100},"w":{"k":2},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1"},{"ty":"fl","fillEnabled":true,"c":{"k":[255,255,255,255]},"o":{"k":100},"nm":"Fill 1"},{"ty":"tr","p":{"k":[48.98,-45.27]},"a":{"k":[0,0]},"s":{"k":[100,100]},"r":{"k":0},"o":{"k":100},"sk":{"k":0},"sa":{"k":0}}],"nm":"Ellipse 1"}],"bounds":{"l":-121,"t":-147,"b":95,"r":146},"ip":0,"op":180,"st":0},{"ddd":0,"ind":1,"ty":4,"nm":"Shape Layer 1","ks":{"o":{"k":100},"r":{"k":0},"p":{"k":[300,300,0]},"a":{"k":[0,0,0]},"s":{"k":[100,100,100]}},"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"k":[200,200]},"p":{"k":[0,0]},"nm":"Ellipse Path 1","closed":true},{"d":1,"ty":"el","s":{"k":[200,200]},"p":{"k":[0,0]},"nm":"Ellipse Path 1","closed":true},{"ty":"st","fillEnabled":true,"c":{"k":[255,255,255,255]},"o":{"k":100},"w":{"k":2},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1"},{"ty":"fl","fillEnabled":true,"c":{"k":[201,26,26,255]},"o":{"k":100},"nm":"Fill 1"},{"ty":"tr","p":{"k":[0,0]},"a":{"k":[0,0]},"s":{"k":[100,100]},"r":{"k":0},"o":{"k":100},"sk":{"k":0},"sa":{"k":0}}],"nm":"Ellipse 1"}],"bounds":{"l":-137,"t":-137,"b":137,"r":137},"ip":0,"op":180,"st":0}],"ip":0,"op":180,"fr":60,"w":600,"h":600}

View File

@@ -0,0 +1 @@
{"assets":[],"v":"4.1.7","ddd":0,"layers":[{"ddd":0,"ind":0,"ty":4,"nm":"Shape Layer 1","td":1,"ks":{"o":{"k":100},"r":{"k":0},"p":{"k":[306,300,0]},"a":{"k":[0,0,0]},"s":{"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":0,"s":[51.741,51.741,100],"e":[122.667,122.667,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":90,"s":[122.667,122.667,100],"e":[70.07,70.07,100]},{"t":174}]}},"shapes":[{"ty":"gr","it":[{"d":1,"ty":"el","s":{"k":[275.75,275.75]},"p":{"k":[0,0]},"nm":"Ellipse Path 1","closed":true},{"d":1,"ty":"el","s":{"k":[275.75,275.75]},"p":{"k":[0,0]},"nm":"Ellipse Path 1","closed":true},{"ty":"st","fillEnabled":true,"c":{"k":[255,255,255,255]},"o":{"k":100},"w":{"k":2},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1"},{"ty":"fl","fillEnabled":true,"c":{"k":[255,255,255,255]},"o":{"k":100},"nm":"Fill 1"},{"ty":"tr","p":{"k":[-4.789,-1.113]},"a":{"k":[0,0]},"s":{"k":[100,100]},"r":{"k":0},"o":{"k":100},"sk":{"k":0},"sa":{"k":0}}],"nm":"Ellipse 1"}],"bounds":{"l":-193,"t":-189,"b":187,"r":183},"ip":0,"op":180,"st":0},{"ddd":0,"ind":1,"ty":1,"nm":"Cyan Solid 1","tt":2,"ks":{"o":{"k":100},"r":{"k":0},"p":{"k":[300,300,0]},"a":{"k":[300,300,0]},"s":{"k":[{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":0,"s":[100,100,100],"e":[59,59,100]},{"i":{"x":[0.833,0.833,0.833],"y":[0.833,0.833,0.833]},"o":{"x":[0.167,0.167,0.167],"y":[0.167,0.167,0.167]},"n":["0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167","0p833_0p833_0p167_0p167"],"t":90,"s":[59,59,100],"e":[108,108,100]},{"t":174}]}},"sw":600,"sh":600,"sc":"#00ffc7","ip":0,"op":180,"st":0},{"ddd":0,"ind":2,"ty":1,"nm":"Medium Purple Solid 2","td":1,"ks":{"o":{"k":100},"r":{"k":0},"p":{"k":[300,300,0]},"a":{"k":[300,300,0]},"s":{"k":[100,100,100]}},"sw":600,"sh":600,"sc":"#9f5eff","ip":0,"op":180,"st":0},{"ddd":0,"ind":3,"ty":1,"nm":"Medium Purple Solid 1","tt":1,"ks":{"o":{"k":100},"r":{"k":0},"p":{"k":[300,300,0]},"a":{"k":[300,300,0]},"s":{"k":[100,100,100]}},"sw":600,"sh":600,"sc":"#9f5eff","ip":0,"op":180,"st":0}],"ip":0,"op":180,"fr":60,"w":600,"h":600}

View File

@@ -0,0 +1 @@
{"assets":[],"v":"4.1.7","ddd":0,"layers":[{"ddd":0,"ind":0,"ty":4,"nm":"Shape Layer 1","ks":{"o":{"k":100},"r":{"k":0},"p":{"k":[300,300,0]},"a":{"k":[0,0,0]},"s":{"k":[100,100,100]}},"hasMask":true,"masksProperties":[{"cl":true,"inv":false,"mode":"a","pt":{"k":[{"i":{"x":0.833,"y":0.833},"o":{"x":0.167,"y":0.167},"n":"0p833_0p833_0p167_0p167","t":0,"s":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-276,-245],[-201,111.355],[-208.645,-140.645],[30.355,-120]]}],"e":[{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-276,-245],[-253,177.355],[147.355,192.355],[64.355,-153]]}]},{"t":72}]},"o":{"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"n":["0p833_0p833_0p167_0p167"],"t":0,"s":[0],"e":[100]},{"t":30}]},"x":{"k":0},"nm":"Mask 1"},{"cl":true,"inv":false,"mode":"a","pt":{"k":{"i":[[0,0],[0,0],[0,0],[0,0]],"o":[[0,0],[0,0],[0,0],[0,0]],"v":[[-152,-76],[-149,49.355],[-47.645,42.355],[-46.645,-72]]}},"o":{"k":100},"x":{"k":0},"nm":"Mask 2"}],"shapes":[{"ty":"gr","it":[{"ty":"rc","d":1,"s":{"k":[231.355,231.355]},"p":{"k":[0,0]},"r":{"k":20},"nm":"Rectangle Path 1","closed":true},{"ty":"st","fillEnabled":true,"c":{"k":[255,255,255,255]},"o":{"k":100},"w":{"k":2},"lc":1,"lj":1,"ml":4,"nm":"Stroke 1"},{"ty":"fl","fillEnabled":true,"c":{"k":[255,255,255,255]},"o":{"k":100},"nm":"Fill 1"},{"ty":"tr","p":{"k":[-85.322,-4.322]},"a":{"k":[0,0]},"s":{"k":[100,100]},"r":{"k":0},"o":{"k":100},"sk":{"k":0},"sa":{"k":0}}],"nm":"Rectangle 1"}],"bounds":{"l":-277,"t":-196,"b":187,"r":106},"ip":0,"op":180,"st":0}],"ip":0,"op":180,"fr":60,"w":600,"h":600}