Commit 4f91ddfa cgx

引入Lottie

1 个父辈 d34fb20f
正在显示 169 个修改的文件 包含 3678 行增加37 行删除
...@@ -31,6 +31,7 @@ ...@@ -31,6 +31,7 @@
D04B3DC327F6F9390022F8DF /* HomeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D04B3DC227F6F9390022F8DF /* HomeViewController.m */; }; D04B3DC327F6F9390022F8DF /* HomeViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D04B3DC227F6F9390022F8DF /* HomeViewController.m */; };
D076C14327F49DC000340B46 /* TmpViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D076C14227F49DC000340B46 /* TmpViewController.m */; }; D076C14327F49DC000340B46 /* TmpViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D076C14227F49DC000340B46 /* TmpViewController.m */; };
D07F9DE927F4683B0036372F /* DKColorTable.txt in Resources */ = {isa = PBXBuildFile; fileRef = D07F9DE827F4683B0036372F /* DKColorTable.txt */; }; D07F9DE927F4683B0036372F /* DKColorTable.txt in Resources */ = {isa = PBXBuildFile; fileRef = D07F9DE827F4683B0036372F /* DKColorTable.txt */; };
D0930F122801124E006B497A /* BaseNaviController.m in Sources */ = {isa = PBXBuildFile; fileRef = D0930F112801124E006B497A /* BaseNaviController.m */; };
D0B5ECA627F2D9DE003EDFE3 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D0B5ECA527F2D9DE003EDFE3 /* AppDelegate.m */; }; D0B5ECA627F2D9DE003EDFE3 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = D0B5ECA527F2D9DE003EDFE3 /* AppDelegate.m */; };
D0B5ECAC27F2D9DE003EDFE3 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D0B5ECAB27F2D9DE003EDFE3 /* ViewController.m */; }; D0B5ECAC27F2D9DE003EDFE3 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D0B5ECAB27F2D9DE003EDFE3 /* ViewController.m */; };
D0B5ECAF27F2D9DE003EDFE3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D0B5ECAD27F2D9DE003EDFE3 /* Main.storyboard */; }; D0B5ECAF27F2D9DE003EDFE3 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D0B5ECAD27F2D9DE003EDFE3 /* Main.storyboard */; };
...@@ -40,6 +41,11 @@ ...@@ -40,6 +41,11 @@
D0B5ECC827F2E97A003EDFE3 /* MacroFuncUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = D0B5ECC727F2E97A003EDFE3 /* MacroFuncUtil.m */; }; D0B5ECC827F2E97A003EDFE3 /* MacroFuncUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = D0B5ECC727F2E97A003EDFE3 /* MacroFuncUtil.m */; };
D0B5ECD527F2F0B2003EDFE3 /* AdaptationUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = D0B5ECD427F2F0B2003EDFE3 /* AdaptationUtil.m */; }; D0B5ECD527F2F0B2003EDFE3 /* AdaptationUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = D0B5ECD427F2F0B2003EDFE3 /* AdaptationUtil.m */; };
D0B5ECD827F2F1B0003EDFE3 /* ServerAPIUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = D0B5ECD727F2F1B0003EDFE3 /* ServerAPIUtil.m */; }; D0B5ECD827F2F1B0003EDFE3 /* ServerAPIUtil.m in Sources */ = {isa = PBXBuildFile; fileRef = D0B5ECD727F2F1B0003EDFE3 /* ServerAPIUtil.m */; };
D0C09ED728007D9100709D4C /* relax_normal_lottie.json in Resources */ = {isa = PBXBuildFile; fileRef = D0C09ED328007D9100709D4C /* relax_normal_lottie.json */; };
D0C09ED828007D9100709D4C /* 478_lottie.json in Resources */ = {isa = PBXBuildFile; fileRef = D0C09ED428007D9100709D4C /* 478_lottie.json */; };
D0C09ED928007D9100709D4C /* 478normal_lottie.json in Resources */ = {isa = PBXBuildFile; fileRef = D0C09ED528007D9100709D4C /* 478normal_lottie.json */; };
D0C09EDA28007D9100709D4C /* relax_lottie.json in Resources */ = {isa = PBXBuildFile; fileRef = D0C09ED628007D9100709D4C /* relax_lottie.json */; };
D0C09EE028007E5F00709D4C /* BreatheController.m in Sources */ = {isa = PBXBuildFile; fileRef = D0C09EDF28007E5F00709D4C /* BreatheController.m */; };
D0C50B3027FD1BEB00DC68F0 /* PrivacyView.m in Sources */ = {isa = PBXBuildFile; fileRef = D0C50B2F27FD1BEB00DC68F0 /* PrivacyView.m */; }; D0C50B3027FD1BEB00DC68F0 /* PrivacyView.m in Sources */ = {isa = PBXBuildFile; fileRef = D0C50B2F27FD1BEB00DC68F0 /* PrivacyView.m */; };
D0C50B3C27FD2EFD00DC68F0 /* PrivacyViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D0C50B3B27FD2EFD00DC68F0 /* PrivacyViewController.m */; }; D0C50B3C27FD2EFD00DC68F0 /* PrivacyViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = D0C50B3B27FD2EFD00DC68F0 /* PrivacyViewController.m */; };
D0C50B3F27FD381000DC68F0 /* UIView+Extras.m in Sources */ = {isa = PBXBuildFile; fileRef = D0C50B3E27FD381000DC68F0 /* UIView+Extras.m */; }; D0C50B3F27FD381000DC68F0 /* UIView+Extras.m in Sources */ = {isa = PBXBuildFile; fileRef = D0C50B3E27FD381000DC68F0 /* UIView+Extras.m */; };
...@@ -100,6 +106,8 @@ ...@@ -100,6 +106,8 @@
D076C14227F49DC000340B46 /* TmpViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TmpViewController.m; sourceTree = "<group>"; }; D076C14227F49DC000340B46 /* TmpViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = TmpViewController.m; sourceTree = "<group>"; };
D07F9D0627F45CB20036372F /* DKNightVersion.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = DKNightVersion.framework; sourceTree = BUILT_PRODUCTS_DIR; }; D07F9D0627F45CB20036372F /* DKNightVersion.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; path = DKNightVersion.framework; sourceTree = BUILT_PRODUCTS_DIR; };
D07F9DE827F4683B0036372F /* DKColorTable.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DKColorTable.txt; sourceTree = "<group>"; }; D07F9DE827F4683B0036372F /* DKColorTable.txt */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text; path = DKColorTable.txt; sourceTree = "<group>"; };
D0930F102801124E006B497A /* BaseNaviController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BaseNaviController.h; sourceTree = "<group>"; };
D0930F112801124E006B497A /* BaseNaviController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BaseNaviController.m; sourceTree = "<group>"; };
D0B5ECA127F2D9DE003EDFE3 /* DreamSleep.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DreamSleep.app; sourceTree = BUILT_PRODUCTS_DIR; }; D0B5ECA127F2D9DE003EDFE3 /* DreamSleep.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = DreamSleep.app; sourceTree = BUILT_PRODUCTS_DIR; };
D0B5ECA427F2D9DE003EDFE3 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; }; D0B5ECA427F2D9DE003EDFE3 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = "<group>"; };
D0B5ECA527F2D9DE003EDFE3 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; }; D0B5ECA527F2D9DE003EDFE3 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = "<group>"; };
...@@ -120,6 +128,12 @@ ...@@ -120,6 +128,12 @@
D0B5ECD427F2F0B2003EDFE3 /* AdaptationUtil.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AdaptationUtil.m; sourceTree = "<group>"; }; D0B5ECD427F2F0B2003EDFE3 /* AdaptationUtil.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AdaptationUtil.m; sourceTree = "<group>"; };
D0B5ECD627F2F1B0003EDFE3 /* ServerAPIUtil.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ServerAPIUtil.h; sourceTree = "<group>"; }; D0B5ECD627F2F1B0003EDFE3 /* ServerAPIUtil.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ServerAPIUtil.h; sourceTree = "<group>"; };
D0B5ECD727F2F1B0003EDFE3 /* ServerAPIUtil.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ServerAPIUtil.m; sourceTree = "<group>"; }; D0B5ECD727F2F1B0003EDFE3 /* ServerAPIUtil.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ServerAPIUtil.m; sourceTree = "<group>"; };
D0C09ED328007D9100709D4C /* relax_normal_lottie.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = relax_normal_lottie.json; sourceTree = "<group>"; };
D0C09ED428007D9100709D4C /* 478_lottie.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = 478_lottie.json; sourceTree = "<group>"; };
D0C09ED528007D9100709D4C /* 478normal_lottie.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = 478normal_lottie.json; sourceTree = "<group>"; };
D0C09ED628007D9100709D4C /* relax_lottie.json */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.json; path = relax_lottie.json; sourceTree = "<group>"; };
D0C09EDE28007E5F00709D4C /* BreatheController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = BreatheController.h; sourceTree = "<group>"; };
D0C09EDF28007E5F00709D4C /* BreatheController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = BreatheController.m; sourceTree = "<group>"; };
D0C50B2E27FD1BEB00DC68F0 /* PrivacyView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PrivacyView.h; sourceTree = "<group>"; }; D0C50B2E27FD1BEB00DC68F0 /* PrivacyView.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PrivacyView.h; sourceTree = "<group>"; };
D0C50B2F27FD1BEB00DC68F0 /* PrivacyView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PrivacyView.m; sourceTree = "<group>"; }; D0C50B2F27FD1BEB00DC68F0 /* PrivacyView.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = PrivacyView.m; sourceTree = "<group>"; };
D0C50B3A27FD2EFD00DC68F0 /* PrivacyViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PrivacyViewController.h; sourceTree = "<group>"; }; D0C50B3A27FD2EFD00DC68F0 /* PrivacyViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PrivacyViewController.h; sourceTree = "<group>"; };
...@@ -216,6 +230,10 @@ ...@@ -216,6 +230,10 @@
D04567A827F6D018009F0A82 /* Resource */ = { D04567A827F6D018009F0A82 /* Resource */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
D0C09ED428007D9100709D4C /* 478_lottie.json */,
D0C09ED528007D9100709D4C /* 478normal_lottie.json */,
D0C09ED628007D9100709D4C /* relax_lottie.json */,
D0C09ED328007D9100709D4C /* relax_normal_lottie.json */,
D027EE3127FB5464004BBA61 /* pull_down.gif */, D027EE3127FB5464004BBA61 /* pull_down.gif */,
D0B5ECB027F2D9E0003EDFE3 /* Assets.xcassets */, D0B5ECB027F2D9E0003EDFE3 /* Assets.xcassets */,
D07F9DE827F4683B0036372F /* DKColorTable.txt */, D07F9DE827F4683B0036372F /* DKColorTable.txt */,
...@@ -247,6 +265,8 @@ ...@@ -247,6 +265,8 @@
D0B5ECA527F2D9DE003EDFE3 /* AppDelegate.m */, D0B5ECA527F2D9DE003EDFE3 /* AppDelegate.m */,
D04B3DA927F6EEB40022F8DF /* DSTabBarController.h */, D04B3DA927F6EEB40022F8DF /* DSTabBarController.h */,
D04B3DAA27F6EEB40022F8DF /* DSTabBarController.m */, D04B3DAA27F6EEB40022F8DF /* DSTabBarController.m */,
D0930F102801124E006B497A /* BaseNaviController.h */,
D0930F112801124E006B497A /* BaseNaviController.m */,
); );
path = Main; path = Main;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -267,6 +287,8 @@ ...@@ -267,6 +287,8 @@
D01814D427FFCCFA00583D4E /* HomeTableView.m */, D01814D427FFCCFA00583D4E /* HomeTableView.m */,
D01814DD27FFDB6A00583D4E /* HomeTableViewCell.h */, D01814DD27FFDB6A00583D4E /* HomeTableViewCell.h */,
D01814DE27FFDB6A00583D4E /* HomeTableViewCell.m */, D01814DE27FFDB6A00583D4E /* HomeTableViewCell.m */,
D0C09EDE28007E5F00709D4C /* BreatheController.h */,
D0C09EDF28007E5F00709D4C /* BreatheController.m */,
); );
path = Home; path = Home;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -461,13 +483,17 @@ ...@@ -461,13 +483,17 @@
isa = PBXResourcesBuildPhase; isa = PBXResourcesBuildPhase;
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
D0C09ED728007D9100709D4C /* relax_normal_lottie.json in Resources */,
D0C09ED828007D9100709D4C /* 478_lottie.json in Resources */,
D04B3DB327F6F6070022F8DF /* Home.storyboard in Resources */, D04B3DB327F6F6070022F8DF /* Home.storyboard in Resources */,
D027EE3227FB5464004BBA61 /* pull_down.gif in Resources */, D027EE3227FB5464004BBA61 /* pull_down.gif in Resources */,
D07F9DE927F4683B0036372F /* DKColorTable.txt in Resources */, D07F9DE927F4683B0036372F /* DKColorTable.txt in Resources */,
D0B5ECB427F2D9E0003EDFE3 /* LaunchScreen.storyboard in Resources */, D0B5ECB427F2D9E0003EDFE3 /* LaunchScreen.storyboard in Resources */,
D0B5ECB127F2D9E0003EDFE3 /* Assets.xcassets in Resources */, D0B5ECB127F2D9E0003EDFE3 /* Assets.xcassets in Resources */,
D04B3DBD27F6F8090022F8DF /* Profile.storyboard in Resources */, D04B3DBD27F6F8090022F8DF /* Profile.storyboard in Resources */,
D0C09EDA28007D9100709D4C /* relax_lottie.json in Resources */,
D0CFD3D027FB3B920002982B /* launcher@3x.png in Resources */, D0CFD3D027FB3B920002982B /* launcher@3x.png in Resources */,
D0C09ED928007D9100709D4C /* 478normal_lottie.json in Resources */,
D0B5ECAF27F2D9DE003EDFE3 /* Main.storyboard in Resources */, D0B5ECAF27F2D9DE003EDFE3 /* Main.storyboard in Resources */,
D0CFD3D127FB3B920002982B /* launcher.png in Resources */, D0CFD3D127FB3B920002982B /* launcher.png in Resources */,
D0CFD3CF27FB3B920002982B /* launcher@2x.png in Resources */, D0CFD3CF27FB3B920002982B /* launcher@2x.png in Resources */,
...@@ -536,6 +562,7 @@ ...@@ -536,6 +562,7 @@
D0C50B3F27FD381000DC68F0 /* UIView+Extras.m in Sources */, D0C50B3F27FD381000DC68F0 /* UIView+Extras.m in Sources */,
D04B3DBB27F6F7940022F8DF /* AISleepCoachController.m in Sources */, D04B3DBB27F6F7940022F8DF /* AISleepCoachController.m in Sources */,
D027EE2627FB3DC0004BBA61 /* NetLoadingStateView.m in Sources */, D027EE2627FB3DC0004BBA61 /* NetLoadingStateView.m in Sources */,
D0C09EE028007E5F00709D4C /* BreatheController.m in Sources */,
D0C50B4627FD66FB00DC68F0 /* DSConstUtil.m in Sources */, D0C50B4627FD66FB00DC68F0 /* DSConstUtil.m in Sources */,
D01814D227FFCBAF00583D4E /* CWFlowLayout.m in Sources */, D01814D227FFCBAF00583D4E /* CWFlowLayout.m in Sources */,
D01814DF27FFDB6A00583D4E /* HomeTableViewCell.m in Sources */, D01814DF27FFDB6A00583D4E /* HomeTableViewCell.m in Sources */,
...@@ -551,6 +578,7 @@ ...@@ -551,6 +578,7 @@
D0B5ECC827F2E97A003EDFE3 /* MacroFuncUtil.m in Sources */, D0B5ECC827F2E97A003EDFE3 /* MacroFuncUtil.m in Sources */,
D01814E227FFDBB800583D4E /* HomeHeaderView.m in Sources */, D01814E227FFDBB800583D4E /* HomeHeaderView.m in Sources */,
D0C50B3C27FD2EFD00DC68F0 /* PrivacyViewController.m in Sources */, D0C50B3C27FD2EFD00DC68F0 /* PrivacyViewController.m in Sources */,
D0930F122801124E006B497A /* BaseNaviController.m in Sources */,
D01814E8280020F900583D4E /* CWPageControl.m in Sources */, D01814E8280020F900583D4E /* CWPageControl.m in Sources */,
D027EE3027FB52DA004BBA61 /* UIImage+Extras.m in Sources */, D027EE3027FB52DA004BBA61 /* UIImage+Extras.m in Sources */,
D04B3DC327F6F9390022F8DF /* HomeViewController.m in Sources */, D04B3DC327F6F9390022F8DF /* HomeViewController.m in Sources */,
......
//
// BreatheController.h
// DreamSleep
//
// Created by peter on 2022/4/8.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
typedef NS_ENUM(NSInteger, LottieStyle) {
// 均衡呼吸法
LottieStyleBalance,
// 舒睡呼吸法
LottieStyleComfortable
};
///  均衡呼吸法和舒睡4-7-8呼吸法
@interface BreatheController : UIViewController
@property (nonatomic, assign) LottieStyle style;
@end
NS_ASSUME_NONNULL_END
//
// BreatheController.m
// DreamSleep
//
// Created by peter on 2022/4/8.
//
#import "BreatheController.h"
#import <Lottie.h>
@interface BreatheController () <UIPickerViewDataSource, UIPickerViewDelegate>
@property (nonatomic, strong) LOTAnimationView *zoomView;
@property (nonatomic, strong) LOTAnimationView *rotateView;
@property (nonatomic, strong) UIPickerView *pickerView;
@property (nonatomic, strong) UILabel *timeLb;
@property (nonatomic, strong) UILabel *minuteLb;
@property (nonatomic, strong) UIButton *starBtn;
@property (nonatomic, strong) NSArray *dataArr;
@property (nonatomic, assign) NSInteger timeAccount;
@property (nonatomic, copy) NSString *rotateLottieFile;
@property (nonatomic, copy) NSString *zoomLottieFile;
@end
@implementation BreatheController
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = ColorFromHex(0x161E38);
self.dataArr = @[@"1",@"2",@"3",@"4",@"5"];
self.rotateLottieFile = self.style == LottieStyleBalance ? @"relax_normal_lottie.json" : @"478normal_lottie.json";
self.zoomLottieFile = self.style == LottieStyleBalance ? @"relax_lottie.json" : @"478_lottie.json";
[self initView];
}
- (void)initView {
[self.view addSubview:self.rotateView];
[self.view addSubview:self.zoomView];
[self.view addSubview:self.pickerView];
self.timeLb = [UILabel new];
self.timeLb.text = @"放松时长";
[self.view addSubview:self.timeLb];
self.timeLb.textColor = [UIColor whiteColor];
self.timeLb.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium];
[self.timeLb sizeToFit];
self.minuteLb = [UILabel new];
self.minuteLb.text = @"分钟";
[self.view addSubview:self.minuteLb];
self.minuteLb.font = [UIFont systemFontOfSize:16 weight:UIFontWeightMedium];
self.minuteLb.textColor = [UIColor whiteColor];
[self.minuteLb sizeToFit];
[self.view addSubview:self.starBtn];
[self.rotateView mas_makeConstraints:^(MASConstraintMaker *make) {
make.width.height.equalTo(@162);
make.centerX.equalTo(self.view);
make.topMargin.equalTo(self.view).offset(100);
}];
[self.zoomView mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self.view);
make.leftMargin.equalTo(self.view).offset(90);
make.rightMargin.equalTo(self.view).offset(-90);
make.height.equalTo(@300);
}];
[self.pickerView mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.rotateView.mas_bottom).offset(30);
make.left.equalTo(self.timeLb.mas_right);
make.right.equalTo(self.minuteLb.mas_left);
make.height.equalTo(@65);
}];
[self.timeLb mas_makeConstraints:^(MASConstraintMaker *make) {
make.left.equalTo(self.rotateView);
make.centerY.equalTo(self.pickerView.mas_centerY);
}];
[self.minuteLb mas_makeConstraints:^(MASConstraintMaker *make) {
make.right.equalTo(self.rotateView);
make.centerY.equalTo(self.pickerView.mas_centerY);
}];
[self.starBtn mas_makeConstraints:^(MASConstraintMaker *make) {
make.top.equalTo(self.pickerView.mas_bottom).offset(50);
make.width.equalTo(@160);
make.centerX.equalTo(self.zoomView.mas_centerX);
make.height.equalTo(@40);
}];
}
- (void)startBtnClick:(UIButton *)sender {
sender.selected = !sender.selected;
self.rotateView.hidden = YES;
self.timeLb.hidden = YES;
self.minuteLb.hidden = YES;
self.starBtn.hidden = YES;
self.pickerView.hidden = YES;
self.zoomView.hidden = NO;
// self.allAccount = self.timeAccount * 60;
// self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerd:) userInfo:nil repeats:YES];
// [self.streamer play];
}
#pragma mark - UIPickerViewDataSource && UIPickerViewDelegate
- (NSInteger)numberOfComponentsInPickerView:(UIPickerView*)pickerView{
return 1;
}
- (NSInteger)pickerView:(UIPickerView *)pickerView numberOfRowsInComponent:(NSInteger)component{
return self.dataArr.count;
}
- (void)pickerView:(UIPickerView *)pickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {
self.timeAccount = [[self.dataArr objectAtIndex:row] integerValue];
}
- (CGFloat)pickerView:(UIPickerView *)pickerView rowHeightForComponent:(NSInteger)component {
return 35;
}
- (CGFloat)pickerView:(UIPickerView *)pickerView widthForComponent:(NSInteger)component {
return 70;
}
- (NSAttributedString *)pickerView:(UIPickerView *)pickerView attributedTitleForRow:(NSInteger)row forComponent:(NSInteger)component {
NSString *titleString = [self.dataArr objectAtIndex:row];
NSMutableAttributedString *attributedString = [[NSMutableAttributedString alloc] initWithString:titleString];
NSRange range = [titleString rangeOfString:titleString];
[attributedString addAttribute:NSForegroundColorAttributeName value:BrandColor range:range];
[attributedString addAttribute:NSFontAttributeName value:[UIFont systemFontOfSize:18] range:range];
if (@available(iOS 14.0, *)) {
pickerView.subviews[1].backgroundColor = DSClearColor;
}
return attributedString;
}
- (LOTAnimationView *)rotateView {
if(!_rotateView) {
_rotateView = [LOTAnimationView animationNamed:self.rotateLottieFile];
_rotateView.contentMode = UIViewContentModeScaleAspectFit;
_rotateView.loopAnimation = YES;
[_rotateView playWithCompletion:^(BOOL animationFinished) {
DSLog(@"rotateView...");
}];
_rotateView.hidden = NO;
}
return _rotateView;
}
- (LOTAnimationView *)zoomView {
if(!_zoomView) {
_zoomView = [LOTAnimationView animationNamed:self.zoomLottieFile];
_zoomView.contentMode = UIViewContentModeScaleAspectFit;
_zoomView.loopAnimation = YES;
_zoomView.hidden = YES;
[_zoomView playWithCompletion:^(BOOL animationFinished) {
DSLog(@"zoomView...");
}];
}
return _zoomView;
}
- (UIPickerView *)pickerView {
if (!_pickerView) {
_pickerView = [UIPickerView new];
_pickerView.delegate = self;
_pickerView.dataSource = self;
}
return _pickerView;
}
- (UIButton *)starBtn {
if (!_starBtn) {
_starBtn = [UIButton new];
_starBtn.layer.cornerRadius = 20;
_starBtn.layer.masksToBounds = YES;
[_starBtn addTarget:self action:@selector(startBtnClick:) forControlEvents:UIControlEventTouchUpInside];
_starBtn.titleLabel.font = [UIFont systemFontOfSize:16];
_starBtn.backgroundColor = ColorFromHex(0x62C3D5);
[_starBtn setTitle:@"开始放松" forState:UIControlStateNormal];
}
return _starBtn;
}
@end
...@@ -7,6 +7,7 @@ ...@@ -7,6 +7,7 @@
#import "DsMiddleView.h" #import "DsMiddleView.h"
#import "HeaderDataModel.h" #import "HeaderDataModel.h"
#import "BreatheController.h"
@interface DsMiddleView () @interface DsMiddleView ()
@property (nonatomic, strong) UIButton *unityBtn; @property (nonatomic, strong) UIButton *unityBtn;
...@@ -48,8 +49,7 @@ ...@@ -48,8 +49,7 @@
for (int i = 0; i < self.middleImgs.count; i++) { for (int i = 0; i < self.middleImgs.count; i++) {
UIButton *btn = [UIButton new]; UIButton *btn = [UIButton new];
[btn setImage:[UIImage imageNamed:self.middleImgs[i]] forState:UIControlStateNormal]; [btn setBackgroundImage:[UIImage imageNamed:self.middleImgs[i]] forState:UIControlStateNormal];
btn.imageView.contentMode = UIViewContentModeScaleAspectFit;
btn.tag = i; btn.tag = i;
[btn addTarget:self action:@selector(btnAction:) forControlEvents:UIControlEventTouchUpInside]; [btn addTarget:self action:@selector(btnAction:) forControlEvents:UIControlEventTouchUpInside];
[self addSubview:btn]; [self addSubview:btn];
...@@ -68,7 +68,15 @@ ...@@ -68,7 +68,15 @@
- (void)btnAction:(UIButton *)sender { - (void)btnAction:(UIButton *)sender {
DSLog(@"tag:%ld", sender.tag); DSLog(@"tag:%ld", sender.tag);
self.height = 3; if (sender.tag != 0) {
BreatheController *breatheVC = [[BreatheController alloc] init];
breatheVC.style = sender.tag == 1 ? LottieStyleBalance : LottieStyleComfortable;
breatheVC.title = sender.tag == 1 ? @"均衡呼吸法" : @"舒睡4-7-8呼吸法";
self.ds_viewController.hidesBottomBarWhenPushed = YES;
[self.ds_viewController.navigationController pushViewController:breatheVC animated:YES];
self.ds_viewController.hidesBottomBarWhenPushed = NO;
}
} }
@end @end
...@@ -10,7 +10,7 @@ ...@@ -10,7 +10,7 @@
#import "HomeTableViewCell.h" #import "HomeTableViewCell.h"
#import "HomeHeaderView.h" #import "HomeHeaderView.h"
@interface HomeTableView () @interface HomeTableView () <UITableViewDelegate>
@property (nonatomic, strong) HomeHeaderView *headerView; @property (nonatomic, strong) HomeHeaderView *headerView;
@property (nonatomic, strong) DSDataSource *homeDataSource; @property (nonatomic, strong) DSDataSource *homeDataSource;
@end @end
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
- (instancetype)initDemo { - (instancetype)initDemo {
if (self = [super initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight) style:UITableViewStylePlain]) { if (self = [super initWithFrame:CGRectMake(0, 0, kScreenWidth, kScreenHeight) style:UITableViewStylePlain]) {
self.dk_backgroundColorPicker = DKColorPickerWithKey(VCViewBG); self.dk_backgroundColorPicker = DKColorPickerWithKey(VCViewBG);
[self.homeDataSource addDataArray:@[]]; [self.homeDataSource addDataArray:@[@1, @2, @3]];
self.mj_header = [DSGifHeader headerWithRefreshingBlock:^{ self.mj_header = [DSGifHeader headerWithRefreshingBlock:^{
dispatch_after(5.0, dispatch_get_main_queue(), ^{ dispatch_after(5.0, dispatch_get_main_queue(), ^{
[self.mj_header endRefreshing]; [self.mj_header endRefreshing];
...@@ -30,29 +30,17 @@ ...@@ -30,29 +30,17 @@
return self; return self;
} }
- (void)layoutSubviews {
[super layoutSubviews];
[self.headerView mas_makeConstraints:^(MASConstraintMaker *make) {
// banner高度
CGFloat bannerH = 2*(kScreenWidth - 48)/5.0;
// 三分钟即刻入睡按钮宽度
CGFloat width = (kScreenWidth - 2*15 - 14)/2;
CGFloat height = 15 + bannerH + 24 + 133*width/165.0;
make.top.equalTo(self);
make.width.mas_equalTo(self);
make.height.mas_equalTo(height);
}];
}
- (DSDataSource *)homeDataSource { - (DSDataSource *)homeDataSource {
if (!_homeDataSource) { if (!_homeDataSource) {
CellConfigureBlock cellBlock = ^(id cell, id model, NSIndexPath * indexPath) { CellConfigureBlock cellBlock = ^(HomeTableViewCell * cell, id model, NSIndexPath * indexPath) {
cell.textLabel.text = @"chengx";
cell.backgroundColor = BrandColor;
// [cell configureCell:model]; // [cell configureCell:model];
}; };
NSString * const homeCellIdentifier = @"HomeCellIdentifier"; NSString * const homeCellIdentifier = @"HomeCellIdentifier";
_homeDataSource = [[DSDataSource alloc] initWithIdentifier:homeCellIdentifier datas:@[] isSection:NO configureBlock:cellBlock]; _homeDataSource = [[DSDataSource alloc] initWithIdentifier:homeCellIdentifier datas:@[] isSection:NO configureBlock:cellBlock];
self.dataSource = _homeDataSource; self.dataSource = _homeDataSource;
self.delegate = self;
[self registerClass:[HomeTableViewCell class] forCellReuseIdentifier:homeCellIdentifier]; [self registerClass:[HomeTableViewCell class] forCellReuseIdentifier:homeCellIdentifier];
self.tableHeaderView = self.headerView; self.tableHeaderView = self.headerView;
...@@ -62,10 +50,36 @@ ...@@ -62,10 +50,36 @@
- (HomeHeaderView *)headerView { - (HomeHeaderView *)headerView {
if (!_headerView) { if (!_headerView) {
_headerView = [[HomeHeaderView alloc] init]; // banner高度
// [_headerView debugViewShowBorder]; CGFloat bannerH = 2*(kScreenWidth - 48)/5.0;
// 三分钟即刻入睡按钮宽度
CGFloat width = (kScreenWidth - 2*15 - 14)/2;
CGFloat height = 15 + bannerH + 24 + 133*width/165.0;
_headerView = [[HomeHeaderView alloc] initWithFrame:CGRectMake(0, 0, kScreenWidth, height)];
_headerView.backgroundColor = self.backgroundColor;
} }
return _headerView; return _headerView;
} }
#pragma mark - UITableViewDelegate
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 70;
}
- (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section {
return 0.001;
}
- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {
return 0.001;
}
- (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
return [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 0.001)];
}
- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section {
return [[UIView alloc] initWithFrame:CGRectMake(0, 0, 10, 0.001)];
}
@end @end
...@@ -15,11 +15,13 @@ ...@@ -15,11 +15,13 @@
@implementation HomeViewController @implementation HomeViewController
- (void)loadView {
self.view = self.homeTV;
}
- (void)viewDidLoad { - (void)viewDidLoad {
[super viewDidLoad]; [super viewDidLoad];
self.view = self.homeTV;
// 导航栏背景色 // 导航栏背景色
// self.navigationController.navigationBar.dk_barTintColorPicker = DKColorPickerWithKey(NaviBG); // self.navigationController.navigationBar.dk_barTintColorPicker = DKColorPickerWithKey(NaviBG);
......
//
// BaseNaviController.h
// DreamSleep
//
// Created by peter on 2022/4/9.
//
#import <UIKit/UIKit.h>
NS_ASSUME_NONNULL_BEGIN
@interface BaseNaviController : UINavigationController
@end
NS_ASSUME_NONNULL_END
//
// BaseNaviController.m
// DreamSleep
//
// Created by peter on 2022/4/9.
//
#import "BaseNaviController.h"
@interface BaseNaviController ()
@end
@implementation BaseNaviController
- (void)viewDidLoad {
[super viewDidLoad];
}
@end
{"v":"5.6.9","fr":25,"ip":0,"op":187,"w":1000,"h":1000,"nm":"合成 1","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"“图层 2/478呼吸的副本”轮廓","sr":1,"ks":{"o":{"a":0,"k":25,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0],"e":[360]},{"t":187}],"ix":10},"p":{"a":0,"k":[500,513.75,0],"ix":2},"a":{"a":0,"k":[245.5,232.5,0],"ix":1},"s":{"a":0,"k":[163,163,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-46.174,18.172],[-32.738,-11.102],[-27.86,-43.558],[-16.9,-42.921],[27.789,-35.426],[45.467,-13.505],[37.123,6.152],[31.537,24.183],[18.173,34.153],[-5.585,41.366],[-30.972,22.345]],"o":[[46.033,-18.173],[32.669,11.031],[27.931,43.628],[16.83,42.851],[-27.789,35.426],[-45.468,13.505],[-36.982,-6.152],[-31.608,-24.112],[-18.102,-34.225],[5.516,-41.436],[30.971,-22.344]],"v":[[-61.872,-179.393],[65.123,-219.132],[142.693,-109.743],[226.273,9.192],[210.222,140.785],[86.337,207.253],[-36.7,224.082],[-138.876,171.968],[-218.072,87.116],[-237.518,-30.335],[-182.999,-135.058]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.569000004787,0.827000038297,0.875,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[245.104,232.234],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":187,"st":0,"bm":0},{"ddd":0,"ind":2,"ty":4,"nm":"“图层 3/478呼吸的副本”轮廓","sr":1,"ks":{"o":{"a":0,"k":50,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0],"e":[360]},{"t":187}],"ix":10},"p":{"a":0,"k":[500,513.75,0],"ix":2},"a":{"a":0,"k":[244.5,224,0],"ix":1},"s":{"a":0,"k":[163,163,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[19.8,-45.5],[31,-15.3],[50.501,11.1],[42.3,18.4],[5.4,44.7],[-22.6,41.7],[-30.6,21.9],[-39.4,5.2],[-37,-11.3],[-25.3,-33.2],[6.1,-37.7]],"o":[[-19.7,45.4],[-30.9,15.3],[-50.6,-11.1],[-42.2,-18.4],[-5.4,-44.7],[22.6,-41.7],[30.5,-21.8],[39.4,-5.3],[37,11.4],[25.4,33.2],[-6.1,37.7]],"v":[[181.9,88.5],[120.2,206.4],[-12,183.9],[-155.2,158.9],[-236.9,54.5],[-196.3,-80.1],[-121.2,-179],[-12.1,-214.4],[103.9,-210.4],[200.7,-141.1],[236.2,-28.5]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.569000004787,0.827000038297,0.875,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[244.3,223.7],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":187,"st":0,"bm":0},{"ddd":0,"ind":3,"ty":4,"nm":"“图层 4/478呼吸的副本”轮廓","sr":1,"ks":{"o":{"a":0,"k":75,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0],"e":[360]},{"t":187}],"ix":10},"p":{"a":0,"k":[500,513.75,0],"ix":2},"a":{"a":0,"k":[232.5,245.5,0],"ix":1},"s":{"a":0,"k":[163,163,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[18.172,46.174],[-11.101,32.74],[-43.558,27.86],[-42.921,16.9],[-35.426,-27.789],[-13.506,-45.468],[6.152,-37.123],[24.183,-31.537],[34.153,-18.173],[41.366,5.585],[22.345,30.972]],"o":[[-18.173,-46.032],[11.032,-32.668],[43.628,-27.931],[42.851,-16.829],[35.426,27.79],[13.505,45.466],[-6.152,36.982],[-24.112,31.607],[-34.225,18.102],[-41.436,-5.516],[-22.344,-30.971]],"v":[[-179.393,61.872],[-219.133,-65.125],[-109.743,-142.694],[9.192,-226.274],[140.785,-210.223],[207.253,-86.337],[224.082,36.699],[171.968,138.876],[87.116,218.072],[-30.335,237.518],[-135.058,182.999]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.569000004787,0.827000038297,0.875,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[232.234,245.103],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":187,"st":0,"bm":0},{"ddd":0,"ind":4,"ty":4,"nm":"“图层 5/478呼吸的副本”轮廓","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0],"e":[360]},{"t":187}],"ix":10},"p":{"a":0,"k":[500,513.75,0],"ix":2},"a":{"a":0,"k":[224,244.5,0],"ix":1},"s":{"a":0,"k":[163,163,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-45.5,-19.8],[-15.3,-31],[11.1,-50.499],[18.4,-42.3],[44.7,-5.401],[41.7,22.6],[21.9,30.6],[5.2,39.399],[-11.3,37],[-33.2,25.3],[-37.7,-6.1]],"o":[[45.4,19.7],[15.3,30.9],[-11.1,50.601],[-18.4,42.2],[-44.7,5.4],[-41.7,-22.6],[-21.8,-30.5],[-5.3,-39.4],[11.4,-37],[33.2,-25.4],[37.7,6.1]],"v":[[88.5,-181.9],[206.4,-120.2],[183.9,11.999],[158.9,155.2],[54.5,236.9],[-80.1,196.3],[-179,121.2],[-214.4,12.1],[-210.4,-103.9],[-141.1,-200.7],[-28.5,-236.2]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.569000004787,0.827000038297,0.875,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":4,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[223.7,244.3],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":187,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file \ No newline at end of file
{"v":"5.6.9","fr":25,"ip":0,"op":150,"w":500,"h":500,"nm":"放松大图ai","ddd":0,"assets":[],"layers":[{"ddd":0,"ind":1,"ty":4,"nm":"“放松大图ai”轮廓","sr":1,"ks":{"o":{"a":0,"k":100,"ix":11},"r":{"a":1,"k":[{"i":{"x":[0.833],"y":[0.833]},"o":{"x":[0.167],"y":[0.167]},"t":0,"s":[0],"e":[360]},{"t":150}],"ix":10},"p":{"a":0,"k":[250,250,0],"ix":2},"a":{"a":0,"k":[400,400,0],"ix":1},"s":{"a":0,"k":[100,100,100],"ix":6}},"ao":0,"shapes":[{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-57.395,33.138],[33.138,57.395],[57.395,-33.137],[-33.137,-57.395]],"o":[[57.396,-33.137],[-33.137,-57.395],[-57.395,33.137],[33.137,57.396]],"v":[[60,103.923],[103.922,-60],[-60,-103.923],[-103.923,60]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.569000004787,0.827000038297,0.875,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[340,296.134],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 1","np":2,"cix":2,"bm":0,"ix":1,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,66.274],[66.274,0],[0,-66.274],[-66.274,0]],"o":[[0,-66.274],[-66.274,0],[0,66.274],[66.274,0]],"v":[[120,0],[0,-120],[-120,0],[0,120]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.569000004787,0.827000038297,0.875,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[280,400.057],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 2","np":2,"cix":2,"bm":0,"ix":2,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[57.396,33.137],[33.137,-57.394],[-57.395,-33.138],[-33.137,57.396]],"o":[[-57.395,-33.137],[-33.137,57.396],[57.395,33.137],[33.138,-57.394]],"v":[[60,-103.923],[-103.923,-60.001],[-60,103.923],[103.922,59.999]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.569000004787,0.827000038297,0.875,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[340,503.98],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 3","np":2,"cix":2,"bm":0,"ix":3,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[57.396,-33.137],[-33.137,-57.395],[-57.396,33.136],[33.138,57.395]],"o":[[-57.395,33.138],[33.137,57.395],[57.396,-33.138],[-33.137,-57.395]],"v":[[-60,-103.923],[-103.923,60],[60,103.924],[103.922,-60]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.569000004787,0.827000038297,0.875,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[460,503.98],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 4","np":2,"cix":2,"bm":0,"ix":4,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[0,-66.274],[-66.274,0],[0,66.274],[66.274,0]],"o":[[0,66.274],[66.274,0],[0,-66.274],[-66.274,0]],"v":[[-120,0],[0,120],[120,0],[0,-120]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.569000004787,0.827000038297,0.875,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[520,400.057],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 5","np":2,"cix":2,"bm":0,"ix":5,"mn":"ADBE Vector Group","hd":false},{"ty":"gr","it":[{"ind":0,"ty":"sh","ix":1,"ks":{"a":0,"k":{"i":[[-57.395,-33.137],[-33.137,57.395],[57.396,33.137],[33.137,-57.395]],"o":[[57.396,33.137],[33.138,-57.395],[-57.396,-33.137],[-33.137,57.395]],"v":[[-60,103.923],[103.922,60],[60,-103.923],[-103.923,-60]],"c":true},"ix":2},"nm":"路径 1","mn":"ADBE Vector Shape - Group","hd":false},{"ty":"st","c":{"a":0,"k":[0.569000004787,0.827000038297,0.875,1],"ix":3},"o":{"a":0,"k":100,"ix":4},"w":{"a":0,"k":2,"ix":5},"lc":1,"lj":1,"ml":10,"bm":0,"nm":"描边 1","mn":"ADBE Vector Graphic - Stroke","hd":false},{"ty":"tr","p":{"a":0,"k":[460,296.134],"ix":2},"a":{"a":0,"k":[0,0],"ix":1},"s":{"a":0,"k":[100,100],"ix":3},"r":{"a":0,"k":0,"ix":6},"o":{"a":0,"k":100,"ix":7},"sk":{"a":0,"k":0,"ix":4},"sa":{"a":0,"k":0,"ix":5},"nm":"变换"}],"nm":"组 6","np":2,"cix":2,"bm":0,"ix":6,"mn":"ADBE Vector Group","hd":false}],"ip":0,"op":150,"st":0,"bm":0}],"markers":[]}
\ No newline at end of file \ No newline at end of file
...@@ -47,6 +47,8 @@ ...@@ -47,6 +47,8 @@
#define DSRed [UIColor redColor] #define DSRed [UIColor redColor]
// 白色 // 白色
#define DSWhite [UIColor whiteColor] #define DSWhite [UIColor whiteColor]
// clearColor
#define DSClearColor [UIColor clearColor]
/** 主title颜色 */ /** 主title颜色 */
#define MainTextColor ColorFromHex(0x333333) #define MainTextColor ColorFromHex(0x333333)
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#import <Foundation/Foundation.h> #import <Foundation/Foundation.h>
typedef void (^CellConfigureBlock)(id cell, id model, NSIndexPath * indexPath); typedef void (^CellConfigureBlock)(id _Nullable cell, id _Nullable model, NSIndexPath * _Nullable indexPath);
NS_ASSUME_NONNULL_BEGIN NS_ASSUME_NONNULL_BEGIN
/** /**
......
...@@ -6,6 +6,7 @@ target 'DreamSleep' do ...@@ -6,6 +6,7 @@ target 'DreamSleep' do
pod 'DKNightVersion', '~> 2.4.3' pod 'DKNightVersion', '~> 2.4.3'
pod 'MJRefresh', '~> 3.7.5' pod 'MJRefresh', '~> 3.7.5'
pod 'Masonry', '~> 1.1.0' pod 'Masonry', '~> 1.1.0'
pod 'lottie-ios', '~> 2.5.3'
end end
# AFNetworking (4.0.1) # AFNetworking (4.0.1)
...@@ -13,3 +14,4 @@ end ...@@ -13,3 +14,4 @@ end
# DKNightVersion (2.4.3) # DKNightVersion (2.4.3)
# MJRefresh (3.7.5) # MJRefresh (3.7.5)
# Masonry (1.1.0) # Masonry (1.1.0)
# lottie-ios (2.5.3)
...@@ -19,6 +19,7 @@ PODS: ...@@ -19,6 +19,7 @@ PODS:
- DKNightVersion/Core - DKNightVersion/Core
- DKNightVersion/UIKit (2.4.3): - DKNightVersion/UIKit (2.4.3):
- DKNightVersion/Core - DKNightVersion/Core
- lottie-ios (2.5.3)
- Masonry (1.1.0) - Masonry (1.1.0)
- MJRefresh (3.7.5) - MJRefresh (3.7.5)
- YTKNetwork (3.0.6): - YTKNetwork (3.0.6):
...@@ -26,6 +27,7 @@ PODS: ...@@ -26,6 +27,7 @@ PODS:
DEPENDENCIES: DEPENDENCIES:
- DKNightVersion (~> 2.4.3) - DKNightVersion (~> 2.4.3)
- lottie-ios (~> 2.5.3)
- Masonry (~> 1.1.0) - Masonry (~> 1.1.0)
- MJRefresh (~> 3.7.5) - MJRefresh (~> 3.7.5)
- YTKNetwork (~> 3.0.6) - YTKNetwork (~> 3.0.6)
...@@ -34,6 +36,7 @@ SPEC REPOS: ...@@ -34,6 +36,7 @@ SPEC REPOS:
trunk: trunk:
- AFNetworking - AFNetworking
- DKNightVersion - DKNightVersion
- lottie-ios
- Masonry - Masonry
- MJRefresh - MJRefresh
- YTKNetwork - YTKNetwork
...@@ -41,10 +44,11 @@ SPEC REPOS: ...@@ -41,10 +44,11 @@ SPEC REPOS:
SPEC CHECKSUMS: SPEC CHECKSUMS:
AFNetworking: 7864c38297c79aaca1500c33288e429c3451fdce AFNetworking: 7864c38297c79aaca1500c33288e429c3451fdce
DKNightVersion: eaa80cc4014b4bae7d4b535fd87ecc6a3c2767b3 DKNightVersion: eaa80cc4014b4bae7d4b535fd87ecc6a3c2767b3
lottie-ios: a50d5c0160425cd4b01b852bb9578963e6d92d31
Masonry: 678fab65091a9290e40e2832a55e7ab731aad201 Masonry: 678fab65091a9290e40e2832a55e7ab731aad201
MJRefresh: fdf5e979eb406a0341468932d1dfc8b7f9fce961 MJRefresh: fdf5e979eb406a0341468932d1dfc8b7f9fce961
YTKNetwork: c16be90b06be003de9e9cd0d3b187cc8eaf35c04 YTKNetwork: c16be90b06be003de9e9cd0d3b187cc8eaf35c04
PODFILE CHECKSUM: c13215e6e4a9ac525d48e4cd5cd0a1c66a74b643 PODFILE CHECKSUM: da4f3494cbd800091ea38764f7f43754ca9369ea
COCOAPODS: 1.11.3 COCOAPODS: 1.11.3
...@@ -19,6 +19,7 @@ PODS: ...@@ -19,6 +19,7 @@ PODS:
- DKNightVersion/Core - DKNightVersion/Core
- DKNightVersion/UIKit (2.4.3): - DKNightVersion/UIKit (2.4.3):
- DKNightVersion/Core - DKNightVersion/Core
- lottie-ios (2.5.3)
- Masonry (1.1.0) - Masonry (1.1.0)
- MJRefresh (3.7.5) - MJRefresh (3.7.5)
- YTKNetwork (3.0.6): - YTKNetwork (3.0.6):
...@@ -26,6 +27,7 @@ PODS: ...@@ -26,6 +27,7 @@ PODS:
DEPENDENCIES: DEPENDENCIES:
- DKNightVersion (~> 2.4.3) - DKNightVersion (~> 2.4.3)
- lottie-ios (~> 2.5.3)
- Masonry (~> 1.1.0) - Masonry (~> 1.1.0)
- MJRefresh (~> 3.7.5) - MJRefresh (~> 3.7.5)
- YTKNetwork (~> 3.0.6) - YTKNetwork (~> 3.0.6)
...@@ -34,6 +36,7 @@ SPEC REPOS: ...@@ -34,6 +36,7 @@ SPEC REPOS:
trunk: trunk:
- AFNetworking - AFNetworking
- DKNightVersion - DKNightVersion
- lottie-ios
- Masonry - Masonry
- MJRefresh - MJRefresh
- YTKNetwork - YTKNetwork
...@@ -41,10 +44,11 @@ SPEC REPOS: ...@@ -41,10 +44,11 @@ SPEC REPOS:
SPEC CHECKSUMS: SPEC CHECKSUMS:
AFNetworking: 7864c38297c79aaca1500c33288e429c3451fdce AFNetworking: 7864c38297c79aaca1500c33288e429c3451fdce
DKNightVersion: eaa80cc4014b4bae7d4b535fd87ecc6a3c2767b3 DKNightVersion: eaa80cc4014b4bae7d4b535fd87ecc6a3c2767b3
lottie-ios: a50d5c0160425cd4b01b852bb9578963e6d92d31
Masonry: 678fab65091a9290e40e2832a55e7ab731aad201 Masonry: 678fab65091a9290e40e2832a55e7ab731aad201
MJRefresh: fdf5e979eb406a0341468932d1dfc8b7f9fce961 MJRefresh: fdf5e979eb406a0341468932d1dfc8b7f9fce961
YTKNetwork: c16be90b06be003de9e9cd0d3b187cc8eaf35c04 YTKNetwork: c16be90b06be003de9e9cd0d3b187cc8eaf35c04
PODFILE CHECKSUM: c13215e6e4a9ac525d48e4cd5cd0a1c66a74b643 PODFILE CHECKSUM: da4f3494cbd800091ea38764f7f43754ca9369ea
COCOAPODS: 1.11.3 COCOAPODS: 1.11.3
...@@ -4,3 +4,4 @@ ${BUILT_PRODUCTS_DIR}/DKNightVersion/DKNightVersion.framework ...@@ -4,3 +4,4 @@ ${BUILT_PRODUCTS_DIR}/DKNightVersion/DKNightVersion.framework
${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework ${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework
${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework ${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework
${BUILT_PRODUCTS_DIR}/YTKNetwork/YTKNetwork.framework ${BUILT_PRODUCTS_DIR}/YTKNetwork/YTKNetwork.framework
${BUILT_PRODUCTS_DIR}/lottie-ios/Lottie.framework
\ No newline at end of file \ No newline at end of file
...@@ -3,3 +3,4 @@ ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DKNightVersion.framework ...@@ -3,3 +3,4 @@ ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DKNightVersion.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJRefresh.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJRefresh.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Masonry.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Masonry.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YTKNetwork.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YTKNetwork.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Lottie.framework
\ No newline at end of file \ No newline at end of file
...@@ -4,3 +4,4 @@ ${BUILT_PRODUCTS_DIR}/DKNightVersion/DKNightVersion.framework ...@@ -4,3 +4,4 @@ ${BUILT_PRODUCTS_DIR}/DKNightVersion/DKNightVersion.framework
${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework ${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework
${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework ${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework
${BUILT_PRODUCTS_DIR}/YTKNetwork/YTKNetwork.framework ${BUILT_PRODUCTS_DIR}/YTKNetwork/YTKNetwork.framework
${BUILT_PRODUCTS_DIR}/lottie-ios/Lottie.framework
\ No newline at end of file \ No newline at end of file
...@@ -3,3 +3,4 @@ ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DKNightVersion.framework ...@@ -3,3 +3,4 @@ ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DKNightVersion.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJRefresh.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJRefresh.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Masonry.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Masonry.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YTKNetwork.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YTKNetwork.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Lottie.framework
\ No newline at end of file \ No newline at end of file
...@@ -4,3 +4,4 @@ ${BUILT_PRODUCTS_DIR}/DKNightVersion/DKNightVersion.framework ...@@ -4,3 +4,4 @@ ${BUILT_PRODUCTS_DIR}/DKNightVersion/DKNightVersion.framework
${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework ${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework
${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework ${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework
${BUILT_PRODUCTS_DIR}/YTKNetwork/YTKNetwork.framework ${BUILT_PRODUCTS_DIR}/YTKNetwork/YTKNetwork.framework
${BUILT_PRODUCTS_DIR}/lottie-ios/Lottie.framework
\ No newline at end of file \ No newline at end of file
...@@ -3,3 +3,4 @@ ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DKNightVersion.framework ...@@ -3,3 +3,4 @@ ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/DKNightVersion.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJRefresh.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/MJRefresh.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Masonry.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Masonry.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YTKNetwork.framework ${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/YTKNetwork.framework
${TARGET_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/Lottie.framework
\ No newline at end of file \ No newline at end of file
...@@ -181,6 +181,7 @@ if [[ "$CONFIGURATION" == "Beta" ]]; then ...@@ -181,6 +181,7 @@ if [[ "$CONFIGURATION" == "Beta" ]]; then
install_framework "${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework" install_framework "${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework"
install_framework "${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework" install_framework "${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework"
install_framework "${BUILT_PRODUCTS_DIR}/YTKNetwork/YTKNetwork.framework" install_framework "${BUILT_PRODUCTS_DIR}/YTKNetwork/YTKNetwork.framework"
install_framework "${BUILT_PRODUCTS_DIR}/lottie-ios/Lottie.framework"
fi fi
if [[ "$CONFIGURATION" == "Debug" ]]; then if [[ "$CONFIGURATION" == "Debug" ]]; then
install_framework "${BUILT_PRODUCTS_DIR}/AFNetworking/AFNetworking.framework" install_framework "${BUILT_PRODUCTS_DIR}/AFNetworking/AFNetworking.framework"
...@@ -188,6 +189,7 @@ if [[ "$CONFIGURATION" == "Debug" ]]; then ...@@ -188,6 +189,7 @@ if [[ "$CONFIGURATION" == "Debug" ]]; then
install_framework "${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework" install_framework "${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework"
install_framework "${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework" install_framework "${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework"
install_framework "${BUILT_PRODUCTS_DIR}/YTKNetwork/YTKNetwork.framework" install_framework "${BUILT_PRODUCTS_DIR}/YTKNetwork/YTKNetwork.framework"
install_framework "${BUILT_PRODUCTS_DIR}/lottie-ios/Lottie.framework"
fi fi
if [[ "$CONFIGURATION" == "Release" ]]; then if [[ "$CONFIGURATION" == "Release" ]]; then
install_framework "${BUILT_PRODUCTS_DIR}/AFNetworking/AFNetworking.framework" install_framework "${BUILT_PRODUCTS_DIR}/AFNetworking/AFNetworking.framework"
...@@ -195,6 +197,7 @@ if [[ "$CONFIGURATION" == "Release" ]]; then ...@@ -195,6 +197,7 @@ if [[ "$CONFIGURATION" == "Release" ]]; then
install_framework "${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework" install_framework "${BUILT_PRODUCTS_DIR}/MJRefresh/MJRefresh.framework"
install_framework "${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework" install_framework "${BUILT_PRODUCTS_DIR}/Masonry/Masonry.framework"
install_framework "${BUILT_PRODUCTS_DIR}/YTKNetwork/YTKNetwork.framework" install_framework "${BUILT_PRODUCTS_DIR}/YTKNetwork/YTKNetwork.framework"
install_framework "${BUILT_PRODUCTS_DIR}/lottie-ios/Lottie.framework"
fi fi
if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then if [ "${COCOAPODS_PARALLEL_CODE_SIGN}" == "true" ]; then
wait wait
......
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DKNightVersion" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/YTKNetwork" FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DKNightVersion" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/YTKNetwork" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DKNightVersion/DKNightVersion.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YTKNetwork/YTKNetwork.framework/Headers" HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DKNightVersion/DKNightVersion.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YTKNetwork/YTKNetwork.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios/Lottie.framework/Headers"
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "CFNetwork" -framework "DKNightVersion" -framework "Foundation" -framework "MJRefresh" -framework "Masonry" -framework "UIKit" -framework "YTKNetwork" OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "CFNetwork" -framework "DKNightVersion" -framework "Foundation" -framework "Lottie" -framework "MJRefresh" -framework "Masonry" -framework "UIKit" -framework "YTKNetwork"
PODS_BUILD_DIR = ${BUILD_DIR} PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
......
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DKNightVersion" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/YTKNetwork" FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DKNightVersion" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/YTKNetwork" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DKNightVersion/DKNightVersion.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YTKNetwork/YTKNetwork.framework/Headers" HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DKNightVersion/DKNightVersion.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YTKNetwork/YTKNetwork.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios/Lottie.framework/Headers"
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "CFNetwork" -framework "DKNightVersion" -framework "Foundation" -framework "MJRefresh" -framework "Masonry" -framework "UIKit" -framework "YTKNetwork" OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "CFNetwork" -framework "DKNightVersion" -framework "Foundation" -framework "Lottie" -framework "MJRefresh" -framework "Masonry" -framework "UIKit" -framework "YTKNetwork"
PODS_BUILD_DIR = ${BUILD_DIR} PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
......
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DKNightVersion" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/YTKNetwork" FRAMEWORK_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking" "${PODS_CONFIGURATION_BUILD_DIR}/DKNightVersion" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry" "${PODS_CONFIGURATION_BUILD_DIR}/YTKNetwork" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios"
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1 GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DKNightVersion/DKNightVersion.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YTKNetwork/YTKNetwork.framework/Headers" HEADER_SEARCH_PATHS = $(inherited) "${PODS_CONFIGURATION_BUILD_DIR}/AFNetworking/AFNetworking.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/DKNightVersion/DKNightVersion.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/MJRefresh/MJRefresh.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/Masonry/Masonry.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/YTKNetwork/YTKNetwork.framework/Headers" "${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios/Lottie.framework/Headers"
LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks' LD_RUNPATH_SEARCH_PATHS = $(inherited) '@executable_path/Frameworks' '@loader_path/Frameworks'
OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "CFNetwork" -framework "DKNightVersion" -framework "Foundation" -framework "MJRefresh" -framework "Masonry" -framework "UIKit" -framework "YTKNetwork" OTHER_LDFLAGS = $(inherited) -framework "AFNetworking" -framework "CFNetwork" -framework "DKNightVersion" -framework "Foundation" -framework "Lottie" -framework "MJRefresh" -framework "Masonry" -framework "UIKit" -framework "YTKNetwork"
PODS_BUILD_DIR = ${BUILD_DIR} PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME) PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_PODFILE_DIR_PATH = ${SRCROOT}/. PODS_PODFILE_DIR_PATH = ${SRCROOT}/.
......
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>${PRODUCT_BUNDLE_IDENTIFIER}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>2.5.3</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
#import <Foundation/Foundation.h>
@interface PodsDummy_lottie_ios : NSObject
@end
@implementation PodsDummy_lottie_ios
@end
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#else
#ifndef FOUNDATION_EXPORT
#if defined(__cplusplus)
#define FOUNDATION_EXPORT extern "C"
#else
#define FOUNDATION_EXPORT extern
#endif
#endif
#endif
#import "LOTAnimatedControl.h"
#import "LOTAnimatedSwitch.h"
#import "LOTAnimationCache.h"
#import "LOTAnimationTransitionController.h"
#import "LOTAnimationView.h"
#import "LOTAnimationView_Compat.h"
#import "LOTBlockCallback.h"
#import "LOTCacheProvider.h"
#import "LOTComposition.h"
#import "LOTInterpolatorCallback.h"
#import "LOTKeypath.h"
#import "Lottie.h"
#import "LOTValueCallback.h"
#import "LOTValueDelegate.h"
FOUNDATION_EXPORT double LottieVersionNumber;
FOUNDATION_EXPORT const unsigned char LottieVersionString[];
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_LDFLAGS = $(inherited) -framework "UIKit"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/lottie-ios
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
framework module Lottie {
umbrella header "lottie-ios-umbrella.h"
export *
module * { export * }
}
CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = NO
CONFIGURATION_BUILD_DIR = ${PODS_CONFIGURATION_BUILD_DIR}/lottie-ios
GCC_PREPROCESSOR_DEFINITIONS = $(inherited) COCOAPODS=1
OTHER_LDFLAGS = $(inherited) -framework "UIKit"
PODS_BUILD_DIR = ${BUILD_DIR}
PODS_CONFIGURATION_BUILD_DIR = ${PODS_BUILD_DIR}/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)
PODS_ROOT = ${SRCROOT}
PODS_TARGET_SRCROOT = ${PODS_ROOT}/lottie-ios
PODS_XCFRAMEWORKS_BUILD_DIR = $(PODS_CONFIGURATION_BUILD_DIR)/XCFrameworkIntermediates
PRODUCT_BUNDLE_IDENTIFIER = org.cocoapods.${PRODUCT_NAME:rfc1034identifier}
SKIP_INSTALL = YES
USE_RECURSIVE_SCRIPT_INPUTS_IN_SCRIPT_PHASES = YES
//
// LOTCompositionContainer.h
// Lottie
//
// Created by brandon_withrow on 7/18/17.
// Copyright © 2017 Airbnb. All rights reserved.
//
#import "LOTLayerContainer.h"
#import "LOTAssetGroup.h"
@interface LOTCompositionContainer : LOTLayerContainer
- (instancetype _Nonnull)initWithModel:(LOTLayer * _Nullable)layer
inLayerGroup:(LOTLayerGroup * _Nullable)layerGroup
withLayerGroup:(LOTLayerGroup * _Nullable)childLayerGroup
withAssestGroup:(LOTAssetGroup * _Nullable)assetGroup;
- (nullable NSArray *)keysForKeyPath:(nonnull LOTKeypath *)keypath;
- (CGPoint)convertPoint:(CGPoint)point
toKeypathLayer:(nonnull LOTKeypath *)keypath
withParentLayer:(CALayer *_Nonnull)parent;
- (CGRect)convertRect:(CGRect)rect
toKeypathLayer:(nonnull LOTKeypath *)keypath
withParentLayer:(CALayer *_Nonnull)parent;
- (CGPoint)convertPoint:(CGPoint)point
fromKeypathLayer:(nonnull LOTKeypath *)keypath
withParentLayer:(CALayer *_Nonnull)parent;
- (CGRect)convertRect:(CGRect)rect
fromKeypathLayer:(nonnull LOTKeypath *)keypath
withParentLayer:(CALayer *_Nonnull)parent;
- (void)addSublayer:(nonnull CALayer *)subLayer
toKeypathLayer:(nonnull LOTKeypath *)keypath;
- (void)maskSublayer:(nonnull CALayer *)subLayer
toKeypathLayer:(nonnull LOTKeypath *)keypath;
@property (nonatomic, readonly, nonnull) NSArray<LOTLayerContainer *> *childLayers;
@property (nonatomic, readonly, nonnull) NSDictionary *childMap;
@end
//
// LOTCompositionContainer.m
// Lottie
//
// Created by brandon_withrow on 7/18/17.
// Copyright © 2017 Airbnb. All rights reserved.
//
#import "LOTCompositionContainer.h"
#import "LOTAsset.h"
#import "CGGeometry+LOTAdditions.h"
#import "LOTHelpers.h"
#import "LOTValueInterpolator.h"
#import "LOTAnimatorNode.h"
#import "LOTRenderNode.h"
#import "LOTRenderGroup.h"
#import "LOTNumberInterpolator.h"
@implementation LOTCompositionContainer {
NSNumber *_frameOffset;
CALayer *DEBUG_Center;
NSMutableDictionary *_keypathCache;
LOTNumberInterpolator *_timeInterpolator;
}
- (instancetype)initWithModel:(LOTLayer *)layer
inLayerGroup:(LOTLayerGroup *)layerGroup
withLayerGroup:(LOTLayerGroup *)childLayerGroup
withAssestGroup:(LOTAssetGroup *)assetGroup {
self = [super initWithModel:layer inLayerGroup:layerGroup];
if (self) {
DEBUG_Center = [CALayer layer];
DEBUG_Center.bounds = CGRectMake(0, 0, 20, 20);
DEBUG_Center.borderColor = [UIColor orangeColor].CGColor;
DEBUG_Center.borderWidth = 2;
DEBUG_Center.masksToBounds = YES;
if (ENABLE_DEBUG_SHAPES) {
[self.wrapperLayer addSublayer:DEBUG_Center];
}
if (layer.startFrame != nil) {
_frameOffset = layer.startFrame;
} else {
_frameOffset = @0;
}
if (layer.timeRemapping) {
_timeInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:layer.timeRemapping.keyframes];
}
[self initializeWithChildGroup:childLayerGroup withAssetGroup:assetGroup];
}
return self;
}
- (void)initializeWithChildGroup:(LOTLayerGroup *)childGroup
withAssetGroup:(LOTAssetGroup *)assetGroup {
NSMutableDictionary *childMap = [NSMutableDictionary dictionary];
NSMutableArray *children = [NSMutableArray array];
NSArray *reversedItems = [[childGroup.layers reverseObjectEnumerator] allObjects];
CALayer *maskedLayer = nil;
for (LOTLayer *layer in reversedItems) {
LOTAsset *asset;
if (layer.referenceID) {
// Get relevant Asset
asset = [assetGroup assetModelForID:layer.referenceID];
}
LOTLayerContainer *child = nil;
if (asset.layerGroup) {
// Layer is a precomp
LOTCompositionContainer *compLayer = [[LOTCompositionContainer alloc] initWithModel:layer inLayerGroup:childGroup withLayerGroup:asset.layerGroup withAssestGroup:assetGroup];
child = compLayer;
} else {
child = [[LOTLayerContainer alloc] initWithModel:layer inLayerGroup:childGroup];
}
if (maskedLayer) {
maskedLayer.mask = child;
maskedLayer = nil;
} else {
if (layer.matteType == LOTMatteTypeAdd) {
maskedLayer = child;
}
[self.wrapperLayer addSublayer:child];
}
[children addObject:child];
if (child.layerName) {
[childMap setObject:child forKey:child.layerName];
}
}
_childMap = childMap;
_childLayers = children;
}
- (void)displayWithFrame:(NSNumber *)frame forceUpdate:(BOOL)forceUpdate {
if (ENABLE_DEBUG_LOGGING) NSLog(@"-------------------- Composition Displaying Frame %@ --------------------", frame);
[super displayWithFrame:frame forceUpdate:forceUpdate];
NSNumber *newFrame = @((frame.floatValue - _frameOffset.floatValue) / self.timeStretchFactor.floatValue);
if (_timeInterpolator) {
newFrame = @([_timeInterpolator floatValueForFrame:newFrame]);
}
for (LOTLayerContainer *child in _childLayers) {
[child displayWithFrame:newFrame forceUpdate:forceUpdate];
}
if (ENABLE_DEBUG_LOGGING) NSLog(@"-------------------- ------------------------------- --------------------");
if (ENABLE_DEBUG_LOGGING) NSLog(@"-------------------- ------------------------------- --------------------");
}
- (void)setViewportBounds:(CGRect)viewportBounds {
[super setViewportBounds:viewportBounds];
for (LOTLayerContainer *layer in _childLayers) {
layer.viewportBounds = viewportBounds;
}
}
- (void)searchNodesForKeypath:(LOTKeypath * _Nonnull)keypath {
if (self.layerName != nil) {
[super searchNodesForKeypath:keypath];
}
if (self.layerName == nil ||
[keypath pushKey:self.layerName]) {
for (LOTLayerContainer *child in _childLayers) {
[child searchNodesForKeypath:keypath];
}
if (self.layerName != nil) {
[keypath popKey];
}
}
}
- (void)setValueDelegate:(id<LOTValueDelegate> _Nonnull)delegate
forKeypath:(LOTKeypath * _Nonnull)keypath {
if (self.layerName != nil) {
[super setValueDelegate:delegate forKeypath:keypath];
}
if (self.layerName == nil ||
[keypath pushKey:self.layerName]) {
for (LOTLayerContainer *child in _childLayers) {
[child setValueDelegate:delegate forKeypath:keypath];
}
if (self.layerName != nil) {
[keypath popKey];
}
}
}
- (nullable NSArray *)keysForKeyPath:(nonnull LOTKeypath *)keypath {
if (_keypathCache == nil) {
_keypathCache = [NSMutableDictionary dictionary];
}
[self searchNodesForKeypath:keypath];
[_keypathCache addEntriesFromDictionary:keypath.searchResults];
return keypath.searchResults.allKeys;
}
- (CALayer *)_layerForKeypath:(nonnull LOTKeypath *)keypath {
id node = _keypathCache[keypath.absoluteKeypath];
if (node == nil) {
[self keysForKeyPath:keypath];
node = _keypathCache[keypath.absoluteKeypath];
}
if (node == nil) {
NSLog(@"LOTComposition could not find layer for keypath:%@", keypath.absoluteKeypath);
return nil;
}
if ([node isKindOfClass:[CALayer class]]) {
return (CALayer *)node;
}
if (![node isKindOfClass:[LOTRenderNode class]]) {
NSLog(@"LOTComposition: Keypath return non-layer node:%@ ", keypath.absoluteKeypath);
return nil;
}
if ([node isKindOfClass:[LOTRenderGroup class]]) {
return [(LOTRenderGroup *)node containerLayer];
}
LOTRenderNode *renderNode = (LOTRenderNode *)node;
return renderNode.outputLayer;
}
- (CGPoint)convertPoint:(CGPoint)point
toKeypathLayer:(nonnull LOTKeypath *)keypath
withParentLayer:(CALayer *_Nonnull)parent{
CALayer *layer = [self _layerForKeypath:keypath];
if (!layer) {
return CGPointZero;
}
return [parent convertPoint:point toLayer:layer];
}
- (CGRect)convertRect:(CGRect)rect
toKeypathLayer:(nonnull LOTKeypath *)keypath
withParentLayer:(CALayer *_Nonnull)parent{
CALayer *layer = [self _layerForKeypath:keypath];
if (!layer) {
return CGRectZero;
}
return [parent convertRect:rect toLayer:layer];
}
- (CGPoint)convertPoint:(CGPoint)point
fromKeypathLayer:(nonnull LOTKeypath *)keypath
withParentLayer:(CALayer *_Nonnull)parent{
CALayer *layer = [self _layerForKeypath:keypath];
if (!layer) {
return CGPointZero;
}
return [parent convertPoint:point fromLayer:layer];
}
- (CGRect)convertRect:(CGRect)rect
fromKeypathLayer:(nonnull LOTKeypath *)keypath
withParentLayer:(CALayer *_Nonnull)parent{
CALayer *layer = [self _layerForKeypath:keypath];
if (!layer) {
return CGRectZero;
}
return [parent convertRect:rect fromLayer:layer];
}
- (void)addSublayer:(nonnull CALayer *)subLayer
toKeypathLayer:(nonnull LOTKeypath *)keypath {
CALayer *layer = [self _layerForKeypath:keypath];
if (layer) {
[layer addSublayer:subLayer];
}
}
- (void)maskSublayer:(nonnull CALayer *)subLayer
toKeypathLayer:(nonnull LOTKeypath *)keypath {
CALayer *layer = [self _layerForKeypath:keypath];
if (layer) {
[layer.superlayer addSublayer:subLayer];
[layer removeFromSuperlayer];
subLayer.mask = layer;
}
}
@end
//
// LOTLayerContainer.h
// Lottie
//
// Created by brandon_withrow on 7/18/17.
// Copyright © 2017 Airbnb. All rights reserved.
//
#import "LOTPlatformCompat.h"
#import "LOTLayer.h"
#import "LOTLayerGroup.h"
#import "LOTKeypath.h"
#import "LOTValueDelegate.h"
@class LOTValueCallback;
@interface LOTLayerContainer : CALayer
- (instancetype _Nonnull)initWithModel:(LOTLayer * _Nullable)layer
inLayerGroup:(LOTLayerGroup * _Nullable)layerGroup;
@property (nonatomic, readonly, strong, nullable) NSString *layerName;
@property (nonatomic, nullable) NSNumber *currentFrame;
@property (nonatomic, readonly, nonnull) NSNumber *timeStretchFactor;
@property (nonatomic, assign) CGRect viewportBounds;
@property (nonatomic, readonly, nonnull) CALayer *wrapperLayer;
@property (nonatomic, readonly, nonnull) NSDictionary *valueInterpolators;
- (void)displayWithFrame:(NSNumber * _Nonnull)frame;
- (void)displayWithFrame:(NSNumber * _Nonnull)frame forceUpdate:(BOOL)forceUpdate;
- (void)searchNodesForKeypath:(LOTKeypath * _Nonnull)keypath;
- (void)setValueDelegate:(id<LOTValueDelegate> _Nonnull)delegate
forKeypath:(LOTKeypath * _Nonnull)keypath;
@end
//
// LOTMaskContainer.h
// Lottie
//
// Created by brandon_withrow on 7/19/17.
// Copyright © 2017 Airbnb. All rights reserved.
//
#import <QuartzCore/QuartzCore.h>
#import "LOTMask.h"
@interface LOTMaskContainer : CALayer
- (instancetype _Nonnull)initWithMasks:(NSArray<LOTMask *> * _Nonnull)masks;
@property (nonatomic, strong, nullable) NSNumber *currentFrame;
@end
//
// LOTMaskContainer.m
// Lottie
//
// Created by brandon_withrow on 7/19/17.
// Copyright © 2017 Airbnb. All rights reserved.
//
#import "LOTMaskContainer.h"
#import "LOTPathInterpolator.h"
#import "LOTNumberInterpolator.h"
@interface LOTMaskNodeLayer : CAShapeLayer
@property (nonatomic, readonly) LOTMask *maskNode;
- (instancetype)initWithMask:(LOTMask *)maskNode;
- (BOOL)hasUpdateForFrame:(NSNumber *)frame;
@end
@implementation LOTMaskNodeLayer {
LOTPathInterpolator *_pathInterpolator;
LOTNumberInterpolator *_opacityInterpolator;
LOTNumberInterpolator *_expansionInterpolator;
}
- (instancetype)initWithMask:(LOTMask *)maskNode {
self = [super init];
if (self) {
_pathInterpolator = [[LOTPathInterpolator alloc] initWithKeyframes:maskNode.maskPath.keyframes];
_opacityInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:maskNode.opacity.keyframes];
_expansionInterpolator = [[LOTNumberInterpolator alloc] initWithKeyframes:maskNode.expansion.keyframes];
_maskNode = maskNode;
self.fillColor = [UIColor blueColor].CGColor;
}
return self;
}
- (void)updateForFrame:(NSNumber *)frame withViewBounds:(CGRect)viewBounds {
if ([self hasUpdateForFrame:frame]) {
LOTBezierPath *path = [_pathInterpolator pathForFrame:frame cacheLengths:NO];
if (self.maskNode.maskMode == LOTMaskModeSubtract) {
CGMutablePathRef pathRef = CGPathCreateMutable();
CGPathAddRect(pathRef, NULL, viewBounds);
CGPathAddPath(pathRef, NULL, path.CGPath);
self.path = pathRef;
self.fillRule = @"even-odd";
CGPathRelease(pathRef);
} else {
self.path = path.CGPath;
}
self.opacity = [_opacityInterpolator floatValueForFrame:frame];
}
}
- (BOOL)hasUpdateForFrame:(NSNumber *)frame {
return ([_pathInterpolator hasUpdateForFrame:frame] ||
[_opacityInterpolator hasUpdateForFrame:frame]);
}
@end
@implementation LOTMaskContainer {
NSArray<LOTMaskNodeLayer *> *_masks;
}
- (instancetype)initWithMasks:(NSArray<LOTMask *> *)masks {
self = [super init];
if (self) {
NSMutableArray *maskNodes = [NSMutableArray array];
CALayer *containerLayer = [CALayer layer];
for (LOTMask *mask in masks) {
LOTMaskNodeLayer *node = [[LOTMaskNodeLayer alloc] initWithMask:mask];
[maskNodes addObject:node];
if (mask.maskMode == LOTMaskModeAdd ||
mask == masks.firstObject) {
[containerLayer addSublayer:node];
} else {
containerLayer.mask = node;
CALayer *newContainer = [CALayer layer];
[newContainer addSublayer:containerLayer];
containerLayer = newContainer;
}
}
[self addSublayer:containerLayer];
_masks = maskNodes;
}
return self;
}
- (void)setCurrentFrame:(NSNumber *)currentFrame {
if (_currentFrame == currentFrame) {
return;
}
_currentFrame = currentFrame;
for (LOTMaskNodeLayer *nodeLayer in _masks) {
[nodeLayer updateForFrame:currentFrame withViewBounds:self.bounds];
}
}
@end
//
// LOTBezierData.h
// Lottie
//
// Created by brandon_withrow on 7/10/17.
// Copyright © 2017 Airbnb. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
NS_ASSUME_NONNULL_BEGIN
@interface LOTBezierData : NSObject
- (instancetype)initWithData:(NSDictionary *)bezierData;
@property (nonatomic, readonly) NSInteger count;
@property (nonatomic, readonly) BOOL closed;
- (CGPoint)vertexAtIndex:(NSInteger)index;
- (CGPoint)inTangentAtIndex:(NSInteger)index;
- (CGPoint)outTangentAtIndex:(NSInteger)index;
@end
NS_ASSUME_NONNULL_END
//
// LOTBezierData.m
// Lottie
//
// Created by brandon_withrow on 7/10/17.
// Copyright © 2017 Airbnb. All rights reserved.
//
#import "LOTBezierData.h"
#import "CGGeometry+LOTAdditions.h"
@implementation LOTBezierData {
CGPoint *_vertices;
CGPoint *_inTangents;
CGPoint *_outTangents;
}
- (instancetype)initWithData:(NSDictionary *)bezierData
{
self = [super init];
if (self) {
[self initializeData:bezierData];
}
return self;
}
- (void)dealloc {
free(_vertices);
free(_inTangents);
free(_outTangents);
}
- (CGPoint)vertexAtIndex:(NSInteger)index {
NSAssert((index < _count &&
index >= 0),
@"Lottie: Index out of bounds");
return _vertices[index];
}
- (CGPoint)inTangentAtIndex:(NSInteger)index {
NSAssert((index < _count &&
index >= 0),
@"Lottie: Index out of bounds");
return _inTangents[index];
}
- (CGPoint)outTangentAtIndex:(NSInteger)index {
NSAssert((index < _count &&
index >= 0),
@"Lottie: Index out of bounds");
return _outTangents[index];
}
- (void)initializeData:(NSDictionary *)bezierData {
NSArray *pointsArray = bezierData[@"v"];
NSArray *inTangents = bezierData[@"i"];
NSArray *outTangents = bezierData[@"o"];
if (pointsArray.count == 0) {
NSLog(@"%s: Warning: shape has no vertices", __PRETTY_FUNCTION__);
return ;
}
NSAssert((pointsArray.count == inTangents.count &&
pointsArray.count == outTangents.count),
@"Lottie: Incorrect number of points and tangents");
_count = pointsArray.count;
_vertices = (CGPoint *)malloc(sizeof(CGPoint) * pointsArray.count);
_inTangents = (CGPoint *)malloc(sizeof(CGPoint) * pointsArray.count);
_outTangents = (CGPoint *)malloc(sizeof(CGPoint) * pointsArray.count);
if (bezierData[@"c"]) {
_closed = [bezierData[@"c"] boolValue];
}
for (int i = 0; i < pointsArray.count; i ++) {
CGPoint vertex = [self _vertexAtIndex:i inArray:pointsArray];
CGPoint outTan = LOT_PointAddedToPoint(vertex, [self _vertexAtIndex:i inArray:outTangents]);
CGPoint inTan = LOT_PointAddedToPoint(vertex, [self _vertexAtIndex:i inArray:inTangents]);
// BW BUG Straight Lines - Test Later
// Bake fix for lines here
_vertices[i] = vertex;
_inTangents[i] = inTan;
_outTangents[i] = outTan;
}
}
- (CGPoint)_vertexAtIndex:(NSInteger)idx inArray:(NSArray *)points {
NSAssert((idx < points.count),
@"Lottie: Vertex Point out of bounds");
NSArray *pointArray = points[idx];
NSAssert((pointArray.count >= 2 &&
[pointArray.firstObject isKindOfClass:[NSNumber class]]),
@"Lottie: Point Data Malformed");
return CGPointMake([(NSNumber *)pointArray[0] floatValue], [(NSNumber *)pointArray[1] floatValue]);
}
@end
//
// LOTKeyframe.h
// Pods
//
// Created by brandon_withrow on 7/10/17.
//
//
#import <Foundation/Foundation.h>
#import <QuartzCore/QuartzCore.h>
#import "LOTPlatformCompat.h"
#import "LOTBezierData.h"
NS_ASSUME_NONNULL_BEGIN
@interface LOTKeyframe : NSObject
- (instancetype)initWithKeyframe:(NSDictionary *)keyframe;
- (instancetype)initWithValue:(id)value;
- (void)remapValueWithBlock:(CGFloat (^)(CGFloat inValue))remapBlock;
- (LOTKeyframe *)copyWithData:(id)data;
@property (nonatomic, readonly) NSNumber *keyframeTime;
@property (nonatomic, readonly) BOOL isHold;
@property (nonatomic, readonly) CGPoint inTangent;
@property (nonatomic, readonly) CGPoint outTangent;
@property (nonatomic, readonly) CGPoint spatialInTangent;
@property (nonatomic, readonly) CGPoint spatialOutTangent;
@property (nonatomic, readonly) CGFloat floatValue;
@property (nonatomic, readonly) CGPoint pointValue;
@property (nonatomic, readonly) CGSize sizeValue;
@property (nonatomic, readonly) UIColor *colorValue;
@property (nonatomic, readonly, nullable) LOTBezierData *pathData;
@property (nonatomic, readonly) NSArray *arrayValue;
@end
@interface LOTKeyframeGroup : NSObject
- (instancetype)initWithData:(id)data;
- (void)remapKeyframesWithBlock:(CGFloat (^)(CGFloat inValue))remapBlock;
@property (nonatomic, readonly) NSArray<LOTKeyframe *> *keyframes;
@end
NS_ASSUME_NONNULL_END
//
// LOTKeyframe.m
// Pods
//
// Created by brandon_withrow on 7/10/17.
//
//
#import "LOTKeyframe.h"
#import "CGGeometry+LOTAdditions.h"
@implementation LOTKeyframe
- (instancetype)initWithKeyframe:(NSDictionary *)keyframe {
self = [super init];
if (self) {
_keyframeTime = keyframe[@"t"];
_inTangent = CGPointZero;
_outTangent = CGPointZero;
_spatialInTangent = CGPointZero;
_spatialOutTangent = CGPointZero;
NSDictionary *timingOutTangent = keyframe[@"o"];
NSDictionary *timingInTangent = keyframe[@"i"];
if (timingInTangent) {
_inTangent = [self _pointFromValueDict:timingInTangent];
}
if (timingOutTangent) {
_outTangent = [self _pointFromValueDict:timingOutTangent];
}
if ([keyframe[@"h"] boolValue]) {
_isHold = YES;
}
if (keyframe[@"to"]) {
NSArray *to = keyframe[@"to"];
_spatialOutTangent = [self _pointFromValueArray:to];
}
if (keyframe[@"ti"]) {
NSArray *ti = keyframe[@"ti"];
_spatialInTangent = [self _pointFromValueArray:ti];
}
id data = keyframe[@"s"];
if (data) {
[self setupOutputWithData:data];
}
}
return self;
}
- (instancetype)initWithValue:(id)value {
self = [super init];
if (self) {
_keyframeTime = @0;
_isHold = YES;
[self setupOutputWithData:value];
}
return self;
}
- (instancetype)initWithLOTKeyframe:(LOTKeyframe *)keyframe {
self = [super init];
if (self) {
_keyframeTime = [keyframe.keyframeTime copy];
_inTangent = keyframe.inTangent;
_outTangent = keyframe.outTangent;
_spatialInTangent = keyframe.spatialInTangent;
_spatialOutTangent = keyframe.spatialOutTangent;
_isHold = keyframe.isHold;
}
return self;
}
- (LOTKeyframe *)copyWithData:(id)data {
LOTKeyframe *newFrame = [[LOTKeyframe alloc] initWithLOTKeyframe:self];
[newFrame setData:data];
return newFrame;
}
- (void)setData:(id)data {
[self setupOutputWithData:data];
}
- (void)remapValueWithBlock:(CGFloat (^)(CGFloat inValue))remapBlock {
_floatValue = remapBlock(_floatValue);
_pointValue = CGPointMake(remapBlock(_pointValue.x), remapBlock(_pointValue.y));
_sizeValue = CGSizeMake(remapBlock(_sizeValue.width), remapBlock(_sizeValue.height));
}
- (void)setupOutputWithData:(id)data {
if ([data isKindOfClass:[NSNumber class]]) {
_floatValue = [(NSNumber *)data floatValue];
}
if ([data isKindOfClass:[NSArray class]] &&
[[(NSArray *)data firstObject] isKindOfClass:[NSNumber class]]) {
NSArray *numberArray = (NSArray *)data;
if (numberArray.count > 0) {
_floatValue = [(NSNumber *)numberArray[0] floatValue];
}
if (numberArray.count > 1) {
_pointValue = CGPointMake(_floatValue = [(NSNumber *)numberArray[0] floatValue],
_floatValue = [(NSNumber *)numberArray[1] floatValue]);
_sizeValue = CGSizeMake(_pointValue.x, _pointValue.y);
}
if (numberArray.count > 3) {
_colorValue = [self _colorValueFromArray:numberArray];
}
_arrayValue = numberArray;
} else if ([data isKindOfClass:[NSArray class]] &&
[[(NSArray *)data firstObject] isKindOfClass:[NSDictionary class]]) {
_pathData = [[LOTBezierData alloc] initWithData:[(NSArray *)data firstObject]];
} else if ([data isKindOfClass:[NSDictionary class]]) {
_pathData = [[LOTBezierData alloc] initWithData:data];
}
}
- (CGPoint)_pointFromValueArray:(NSArray *)values {
CGPoint returnPoint = CGPointZero;
if (values.count > 1) {
returnPoint.x = [(NSNumber *)values[0] floatValue];
returnPoint.y = [(NSNumber *)values[1] floatValue];
}
return returnPoint;
}
- (CGPoint)_pointFromValueDict:(NSDictionary *)values {
NSNumber *xValue = @0, *yValue = @0;
if ([values[@"x"] isKindOfClass:[NSNumber class]]) {
xValue = values[@"x"];
} else if ([values[@"x"] isKindOfClass:[NSArray class]]) {
xValue = values[@"x"][0];
}
if ([values[@"y"] isKindOfClass:[NSNumber class]]) {
yValue = values[@"y"];
} else if ([values[@"y"] isKindOfClass:[NSArray class]]) {
yValue = values[@"y"][0];
}
return CGPointMake([xValue floatValue], [yValue floatValue]);
}
- (UIColor *)_colorValueFromArray:(NSArray<NSNumber *> *)colorArray {
if (colorArray.count == 4) {
BOOL shouldUse255 = NO;
for (NSNumber *number in colorArray) {
if (number.floatValue > 1) {
shouldUse255 = YES;
}
}
return [UIColor colorWithRed:colorArray[0].floatValue / (shouldUse255 ? 255.f : 1.f)
green:colorArray[1].floatValue / (shouldUse255 ? 255.f : 1.f)
blue:colorArray[2].floatValue / (shouldUse255 ? 255.f : 1.f)
alpha:colorArray[3].floatValue / (shouldUse255 ? 255.f : 1.f)];
}
return nil;
}
@end
@implementation LOTKeyframeGroup
- (instancetype)initWithData:(id)data {
self = [super init];
if (self) {
if ([data isKindOfClass:[NSDictionary class]] &&
[(NSDictionary *)data valueForKey:@"k"]) {
[self buildKeyframesFromData:[(NSDictionary *)data valueForKey:@"k"]];
} else {
[self buildKeyframesFromData:data];
}
}
return self;
}
- (void)buildKeyframesFromData:(id)data {
if ([data isKindOfClass:[NSArray class]] &&
[[(NSArray *)data firstObject] isKindOfClass:[NSDictionary class]] &&
[(NSArray *)data firstObject][@"t"]) {
// Array of Keyframes
NSArray *keyframes = (NSArray *)data;
NSMutableArray *keys = [NSMutableArray array];
NSDictionary *previousFrame = nil;
for (NSDictionary *keyframe in keyframes) {
NSMutableDictionary *currentFrame = [NSMutableDictionary dictionary];
if (keyframe[@"t"]) {
// Set time
currentFrame[@"t"] = keyframe[@"t"];
}
if (keyframe[@"s"]) {
// Set Value for Keyframe
currentFrame[@"s"] = keyframe[@"s"];
} else if (previousFrame[@"e"]) {
// Set Value for Keyframe
currentFrame[@"s"] = previousFrame[@"e"];
}
if (keyframe[@"o"]) {
// Set out tangent
currentFrame[@"o"] = keyframe[@"o"];
}
if (previousFrame[@"i"]) {
currentFrame[@"i"] = previousFrame[@"i"];
}
if (keyframe[@"to"]) {
// Set out tangent
currentFrame[@"to"] = keyframe[@"to"];
}
if (previousFrame[@"ti"]) {
currentFrame[@"ti"] = previousFrame[@"ti"];
}
if (keyframe[@"h"]) {
currentFrame[@"h"] = keyframe[@"h"];
}
LOTKeyframe *key = [[LOTKeyframe alloc] initWithKeyframe:currentFrame];
[keys addObject:key];
previousFrame = keyframe;
}
_keyframes = keys;
} else {
LOTKeyframe *key = [[LOTKeyframe alloc] initWithValue:data];
_keyframes = @[key];
}
}
- (void)remapKeyframesWithBlock:(CGFloat (^)(CGFloat))remapBlock {
for (LOTKeyframe *keyframe in _keyframes) {
[keyframe remapValueWithBlock:remapBlock];
}
}
@end
/*
+KeyFrameObject has
+ i (PointObject) // Timing curve in tangent
+ o (PointObject) // Timing curve out tangent
+ n (array of string) // String representation of timing curve
+ t (integer) // Keyframe time for start of keyframe
+ s (float or array of float or PathObject) // The key information
+ e (float or array of float or PathObject) // The end key information
+ to (array of float) // For spacial bezier path interpolation, the in tangent
+ ti (array of float) // For spacial bezier path interpolation, the out tangent
+ h (integer) // If the keyframe is a Hold keyframe or not
*/
#import "LOTPlatformCompat.h"
#import <CoreGraphics/CoreGraphics.h>
//
// Core Graphics Geometry Additions
//
extern const CGSize CGSizeMax;
CGRect LOT_RectIntegral(CGRect rect);
// Centering
// Returns a rectangle of the given size, centered at a point
CGRect LOT_RectCenteredAtPoint(CGPoint center, CGSize size, BOOL integral);
// Returns the center point of a CGRect
CGPoint LOT_RectGetCenterPoint(CGRect rect);
// Insetting
// Inset the rectangle on a single edge
CGRect LOT_RectInsetLeft(CGRect rect, CGFloat inset);
CGRect LOT_RectInsetRight(CGRect rect, CGFloat inset);
CGRect LOT_RectInsetTop(CGRect rect, CGFloat inset);
CGRect LOT_RectInsetBottom(CGRect rect, CGFloat inset);
// Inset the rectangle on two edges
CGRect LOT_RectInsetHorizontal(CGRect rect, CGFloat leftInset, CGFloat rightInset);
CGRect LOT_RectInsetVertical(CGRect rect, CGFloat topInset, CGFloat bottomInset);
// Inset the rectangle on all edges
CGRect LOT_RectInsetAll(CGRect rect, CGFloat leftInset, CGFloat rightInset, CGFloat topInset, CGFloat bottomInset);
// Framing
// Returns a rectangle of size framed in the center of the given rectangle
CGRect LOT_RectFramedCenteredInRect(CGRect rect, CGSize size, BOOL integral);
// Returns a rectangle of size framed in the given rectangle and inset
CGRect LOT_RectFramedLeftInRect(CGRect rect, CGSize size, CGFloat inset, BOOL integral);
CGRect LOT_RectFramedRightInRect(CGRect rect, CGSize size, CGFloat inset, BOOL integral);
CGRect LOT_RectFramedTopInRect(CGRect rect, CGSize size, CGFloat inset, BOOL integral);
CGRect LOT_RectFramedBottomInRect(CGRect rect, CGSize size, CGFloat inset, BOOL integral);
CGRect LOT_RectFramedTopLeftInRect(CGRect rect, CGSize size, CGFloat insetWidth, CGFloat insetHeight, BOOL integral);
CGRect LOT_RectFramedTopRightInRect(CGRect rect, CGSize size, CGFloat insetWidth, CGFloat insetHeight, BOOL integral);
CGRect LOT_RectFramedBottomLeftInRect(CGRect rect, CGSize size, CGFloat insetWidth, CGFloat insetHeight, BOOL integral);
CGRect LOT_RectFramedBottomRightInRect(CGRect rect, CGSize size, CGFloat insetWidth, CGFloat insetHeight, BOOL integral);
// Divides a rect into sections and returns the section at specified index
CGRect LOT_RectDividedSection(CGRect rect, NSInteger sections, NSInteger index, CGRectEdge fromEdge);
// Returns a rectangle of size attached to the given rectangle
CGRect LOT_RectAttachedLeftToRect(CGRect rect, CGSize size, CGFloat margin, BOOL integral);
CGRect LOT_RectAttachedRightToRect(CGRect rect, CGSize size, CGFloat margin, BOOL integral);
CGRect LOT_RectAttachedTopToRect(CGRect rect, CGSize size, CGFloat margin, BOOL integral);
CGRect LOT_RectAttachedBottomToRect(CGRect rect, CGSize size, CGFloat margin, BOOL integral);
CGRect LOT_RectAttachedBottomLeftToRect(CGRect rect, CGSize size, CGFloat marginWidth, CGFloat marginHeight, BOOL integral);
CGRect LOT_RectAttachedBottomRightToRect(CGRect rect, CGSize size, CGFloat marginWidth, CGFloat marginHeight, BOOL integral);
CGRect LOT_RectAttachedTopRightToRect(CGRect rect, CGSize size, CGFloat marginWidth, CGFloat marginHeight, BOOL integral);
CGRect LOT_RectAttachedTopLeftToRect(CGRect rect, CGSize size, CGFloat marginWidth, CGFloat marginHeight, BOOL integral);
BOOL LOT_CGPointIsZero(CGPoint point);
// Combining
// Adds all values of the 2nd rect to the first rect
CGRect LOT_RectAddRect(CGRect rect, CGRect other);
CGRect LOT_RectAddPoint(CGRect rect, CGPoint point);
CGRect LOT_RectAddSize(CGRect rect, CGSize size);
CGRect LOT_RectBounded(CGRect rect);
CGPoint LOT_PointAddedToPoint(CGPoint point1, CGPoint point2);
CGRect LOT_RectSetHeight(CGRect rect, CGFloat height);
CGFloat LOT_PointDistanceFromPoint(CGPoint point1, CGPoint point2);
CGFloat LOT_DegreesToRadians(CGFloat degrees);
CGFloat LOT_RemapValue(CGFloat value, CGFloat low1, CGFloat high1, CGFloat low2, CGFloat high2 );
CGPoint LOT_PointByLerpingPoints(CGPoint point1, CGPoint point2, CGFloat value);
CGPoint LOT_PointInLine(CGPoint A, CGPoint B, CGFloat T);
CGPoint LOT_PointInCubicCurve(CGPoint start, CGPoint cp1, CGPoint cp2, CGPoint end, CGFloat T);
CGFloat LOT_CubicBezierInterpolate(CGPoint P0, CGPoint P1, CGPoint P2, CGPoint P3, CGFloat x);
CGFloat LOT_SolveCubic(CGFloat a, CGFloat b, CGFloat c, CGFloat d);
CGFloat LOT_SolveQuadratic(CGFloat a, CGFloat b, CGFloat c);
CGFloat LOT_Squared(CGFloat f);
CGFloat LOT_Cubed(CGFloat f);
CGFloat LOT_CubicRoot(CGFloat f);
CGFloat LOT_CubicLength(CGPoint fromPoint, CGPoint toPoint, CGPoint controlPoint1, CGPoint controlPoint2);
CGFloat LOT_CubicLengthWithPrecision(CGPoint fromPoint, CGPoint toPoint, CGPoint controlPoint1, CGPoint controlPoint2, CGFloat iterations);
//
// LOTBezierPath.h
// Lottie
//
// Created by brandon_withrow on 7/20/17.
// Copyright © 2017 Airbnb. All rights reserved.
//
#import "LOTPlatformCompat.h"
NS_ASSUME_NONNULL_BEGIN
@interface LOTBezierPath : NSObject
+ (instancetype)pathWithCGPath:(CGPathRef)path;
+ (instancetype)newPath;
- (void)LOT_moveToPoint:(CGPoint)point;
- (void)LOT_addLineToPoint:(CGPoint)point;
- (void)LOT_addCurveToPoint:(CGPoint)point
controlPoint1:(CGPoint)cp1
controlPoint2:(CGPoint)cp2;
- (void)LOT_closePath;
- (void)LOT_removeAllPoints;
- (void)LOT_appendPath:(LOTBezierPath *)bezierPath;
- (void)trimPathFromT:(CGFloat)fromT toT:(CGFloat)toT offset:(CGFloat)offset;
- (void)LOT_applyTransform:(CGAffineTransform)transform;
@property (nonatomic, assign) BOOL cacheLengths;
@property (nonatomic, readonly) CGFloat length;
@property (nonatomic, readonly) CGPathRef CGPath;
@property (nonatomic, readonly) CGPoint currentPoint;
@property (nonatomic) CGFloat lineWidth;
@property (nonatomic) CGLineCap lineCapStyle;
@property (nonatomic) CGLineJoin lineJoinStyle;
@property (nonatomic) CGFloat miterLimit;
@property (nonatomic) CGFloat flatness;
@property (nonatomic) BOOL usesEvenOddFillRule;
@property (readonly, getter=isEmpty) BOOL empty;
@property (nonatomic, readonly) CGRect bounds;
@end
NS_ASSUME_NONNULL_END
//
// LOTHelpers.h
// Lottie
//
// Created by Brandon Withrow on 7/28/16.
// Copyright © 2016 Brandon Withrow. All rights reserved.
//
#ifndef LOTHelpers_h
#define LOTHelpers_h
#import "UIColor+Expanded.h"
#import "CGGeometry+LOTAdditions.h"
#import "LOTBezierPath.h"
#define ENABLE_DEBUG_LOGGING NO
#define ENABLE_DEBUG_SHAPES NO
#endif /* LOTHelpers_h */
// TODO Feature Phase
/*
- Trim Path individually
- Image Cache Support
- Skew transform
*/
//
// LOTAnimationView
// LottieAnimator
//
// Created by Brandon Withrow on 12/14/15.
// Copyright © 2015 Brandon Withrow. All rights reserved.
//
#import <QuartzCore/QuartzCore.h>
#import <Foundation/Foundation.h>
@interface LOTRadialGradientLayer : CALayer
@property CGPoint startPoint;
@property CGPoint endPoint;
@property (nonatomic, copy) NSArray *colors;
@property (nonatomic, copy) NSArray<NSNumber *> *locations;
@property (nonatomic, assign) BOOL isRadial;
@end
//
// LOTAnimationView
// LottieAnimator
//
// Created by Brandon Withrow on 12/14/15.
// Copyright © 2015 Brandon Withrow. All rights reserved.
//
#import "LOTRadialGradientLayer.h"
#import "CGGeometry+LOTAdditions.h"
@implementation LOTRadialGradientLayer
@dynamic isRadial;
@dynamic startPoint;
@dynamic endPoint;
@dynamic colors;
@dynamic locations;
+ (BOOL)needsDisplayForKey:(NSString *)key {
if ([key isEqualToString:@"startPoint"] ||
[key isEqualToString:@"endPoint"] ||
[key isEqualToString:@"colors"] ||
[key isEqualToString:@"locations"] ||
[key isEqualToString:@"isRadial"]) {
return YES;
}
return [super needsDisplayForKey:key];
}
- (id)actionForKey:(NSString *)key {
id action = self.actions[key];
if (action) {
if (action == [NSNull null]) {
return nil;
}
return action;
}
if ([key isEqualToString:@"startPoint"] ||
[key isEqualToString:@"endPoint"] ||
[key isEqualToString:@"colors"] ||
[key isEqualToString:@"locations"] ||
[key isEqualToString:@"isRadial"]) {
CABasicAnimation *theAnimation = [CABasicAnimation animationWithKeyPath:key];
theAnimation.fromValue = [self.presentationLayer valueForKey:key];
return theAnimation;
}
return [super actionForKey:key];
}
- (void)drawInContext:(CGContextRef)ctx {
if (self.colors.count == 0) {
return;
}
NSInteger numberOfLocations = self.locations.count;
CGColorRef colorRef = (__bridge CGColorRef)[self.colors objectAtIndex:0];
NSInteger numberOfComponents = CGColorGetNumberOfComponents(colorRef);
CGColorSpaceRef colorSpace = CGColorGetColorSpace(colorRef);
CGPoint origin = self.startPoint;
CGFloat radius = LOT_PointDistanceFromPoint(self.startPoint, self.endPoint);
CGFloat gradientLocations[numberOfLocations];
CGFloat gradientComponents[numberOfLocations * numberOfComponents];
for (NSInteger locationIndex = 0; locationIndex < numberOfLocations; locationIndex++) {
gradientLocations[locationIndex] = [self.locations[locationIndex] floatValue];
const CGFloat *colorComponents = CGColorGetComponents((__bridge CGColorRef)self.colors[locationIndex]);
for (NSInteger componentIndex = 0; componentIndex < numberOfComponents; componentIndex++) {
gradientComponents[numberOfComponents * locationIndex + componentIndex] = colorComponents[componentIndex];
}
}
CGGradientRef gradient = CGGradientCreateWithColorComponents(colorSpace, gradientComponents, gradientLocations, numberOfLocations);
if (self.isRadial) {
CGContextDrawRadialGradient(ctx, gradient, origin, 0, origin, radius, kCGGradientDrawsAfterEndLocation);
} else {
CGContextDrawLinearGradient(ctx, gradient, self.startPoint, self.endPoint, kCGGradientDrawsBeforeStartLocation | kCGGradientDrawsAfterEndLocation);
}
CGGradientRelease(gradient);
}
@end
#import "LOTPlatformCompat.h"
// From http://github.com/ars/uicolor-utilities
#define CLAMP(val,min,max) MIN(MAX(val,min),max)
@interface UIColor (UIColor_Expanded)
@property (nonatomic, readonly) CGColorSpaceModel colorSpaceModel;
@property (nonatomic, readonly) BOOL canProvideRGBComponents;
@property (nonatomic, readonly) CGFloat red; // Only valid if canProvideRGBComponents is YES
@property (nonatomic, readonly) CGFloat green; // Only valid if canProvideRGBComponents is YES
@property (nonatomic, readonly) CGFloat blue; // Only valid if canProvideRGBComponents is YES
@property (nonatomic, readonly) CGFloat white; // Only valid if colorSpaceModel == kCGColorSpaceModelMonochrome
@property (nonatomic, readonly) CGFloat alpha;
@property (nonatomic, readonly) UInt32 rgbHex;
- (NSString *)LOT_colorSpaceString;
- (NSArray *)LOT_arrayFromRGBAComponents;
- (BOOL)LOT_red:(CGFloat *)r green:(CGFloat *)g blue:(CGFloat *)b alpha:(CGFloat *)a;
- (UIColor *)LOT_colorByLuminanceMapping;
- (UIColor *)LOT_colorByMultiplyingByRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha;
- (UIColor *) LOT_colorByAddingRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha;
- (UIColor *) LOT_colorByLighteningToRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha;
- (UIColor *) LOT_colorByDarkeningToRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha;
- (UIColor *)LOT_colorByMultiplyingBy:(CGFloat)f;
- (UIColor *) LOT_colorByAdding:(CGFloat)f;
- (UIColor *) LOT_colorByLighteningTo:(CGFloat)f;
- (UIColor *) LOT_colorByDarkeningTo:(CGFloat)f;
- (UIColor *)LOT_colorByMultiplyingByColor:(UIColor *)color;
- (UIColor *) LOT_colorByAddingColor:(UIColor *)color;
- (UIColor *) LOT_colorByLighteningToColor:(UIColor *)color;
- (UIColor *) LOT_colorByDarkeningToColor:(UIColor *)color;
- (NSString *)LOT_stringFromColor;
- (NSString *)LOT_hexStringValue;
+ (UIColor *)LOT_randomColor;
+ (UIColor *)LOT_colorWithString:(NSString *)stringToConvert;
+ (UIColor *)LOT_colorWithRGBHex:(UInt32)hex;
+ (UIColor *)LOT_colorWithHexString:(NSString *)stringToConvert;
+ (UIColor *)LOT_colorWithName:(NSString *)cssColorName;
+ (UIColor *)LOT_colorByLerpingFromColor:(UIColor *)fromColor toColor:(UIColor *)toColor amount:(CGFloat)amount;
@end
//
// Created by Oleksii Pavlovskyi on 2/2/17.
// Copyright (c) 2017 Airbnb. All rights reserved.
//
#include <TargetConditionals.h>
#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
#import <Foundation/Foundation.h>
#import <QuartzCore/QuartzCore.h>
@interface CALayer (Compat)
@property (nonatomic, assign) BOOL allowsEdgeAntialiasing;
@end
#endif
//
// Created by Oleksii Pavlovskyi on 2/2/17.
// Copyright (c) 2017 Airbnb. All rights reserved.
//
#include <TargetConditionals.h>
#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
#import "CALayer+Compat.h"
@implementation CALayer (Compat)
- (BOOL)allowsEdgeAntialiasing { return NO; }
- (void)setAllowsEdgeAntialiasing:(BOOL)allowsEdgeAntialiasing { }
@end
#endif
//
// LOTPlatformCompat.h
// Lottie
//
// Created by Oleksii Pavlovskyi on 2/2/17.
// Copyright (c) 2017 Airbnb. All rights reserved.
//
#ifndef LOTPlatformCompat_h
#define LOTPlatformCompat_h
#include <TargetConditionals.h>
#if TARGET_OS_IPHONE || TARGET_OS_SIMULATOR
#import <UIKit/UIKit.h>
#else
#import <AppKit/AppKit.h>
#import "UIColor.h"
#import "CALayer+Compat.h"
#import "NSValue+Compat.h"
#import "UIBezierPath.h"
NS_INLINE NSString *NSStringFromCGRect(CGRect rect) {
return NSStringFromRect(rect);
}
NS_INLINE NSString *NSStringFromCGPoint(CGPoint point) {
return NSStringFromPoint(point);
}
typedef NSEdgeInsets UIEdgeInsets;
#endif
#endif
//
// Created by Oleksii Pavlovskyi on 2/2/17.
// Copyright (c) 2017 Airbnb. All rights reserved.
//
#include <TargetConditionals.h>
#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
#import <Foundation/Foundation.h>
@interface NSValue (Compat)
+ (NSValue *)valueWithCGRect:(CGRect)rect;
+ (NSValue *)valueWithCGPoint:(CGPoint)point;
@property (nonatomic, readonly) CGRect CGRectValue;
@property(nonatomic, readonly) CGPoint CGPointValue;
@property (nonatomic, readonly) CGSize CGSizeValue;
@end
#endif
//
// Created by Oleksii Pavlovskyi on 2/2/17.
// Copyright (c) 2017 Airbnb. All rights reserved.
//
#include <TargetConditionals.h>
#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
#import "NSValue+Compat.h"
@implementation NSValue (Compat)
+ (NSValue *)valueWithCGRect:(CGRect)rect {
return [self valueWithRect:rect];
}
+ (NSValue *)valueWithCGPoint:(CGPoint)point {
return [self valueWithPoint:point];
}
- (CGRect)CGRectValue {
return self.rectValue;
}
- (CGPoint)CGPointValue {
return self.pointValue;
}
- (CGSize)CGSizeValue {
return self.sizeValue;
}
@end
#endif
// Kindly stolen from https://github.com/BigZaphod/Chameleon
/*
* Copyright (c) 2011, The Iconfactory. All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice,
* this list of conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. Neither the name of The Iconfactory nor the names of its contributors may
* be used to endorse or promote products derived from this software without
* specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL THE ICONFACTORY BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
* DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
* LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF
* ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include <TargetConditionals.h>
#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
typedef NS_OPTIONS(NSUInteger, UIRectCorner) {
UIRectCornerTopLeft = 1 << 0,
UIRectCornerTopRight = 1 << 1,
UIRectCornerBottomLeft = 1 << 2,
UIRectCornerBottomRight = 1 << 3,
UIRectCornerAllCorners = UIRectCornerTopLeft | UIRectCornerTopRight | UIRectCornerBottomLeft | UIRectCornerBottomRight
};
@interface UIBezierPath : NSObject <NSCopying>
+ (UIBezierPath *)bezierPath;
+ (UIBezierPath *)bezierPathWithRect:(CGRect)rect;
+ (UIBezierPath *)bezierPathWithOvalInRect:(CGRect)rect;
+ (UIBezierPath *)bezierPathWithRoundedRect:(CGRect)rect cornerRadius:(CGFloat)cornerRadius;
+ (UIBezierPath *)bezierPathWithRoundedRect:(CGRect)rect byRoundingCorners:(UIRectCorner)corners cornerRadii:(CGSize)cornerRadii;
+ (UIBezierPath *)bezierPathWithArcCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;
+ (UIBezierPath *)bezierPathWithCGPath:(CGPathRef)CGPath;
- (void)moveToPoint:(CGPoint)point;
- (void)addLineToPoint:(CGPoint)point;
- (void)addArcWithCenter:(CGPoint)center radius:(CGFloat)radius startAngle:(CGFloat)startAngle endAngle:(CGFloat)endAngle clockwise:(BOOL)clockwise;
- (void)addCurveToPoint:(CGPoint)endPoint controlPoint1:(CGPoint)controlPoint1 controlPoint2:(CGPoint)controlPoint2;
- (void)addQuadCurveToPoint:(CGPoint)endPoint controlPoint:(CGPoint)controlPoint;
- (void)closePath;
- (void)removeAllPoints;
- (void)appendPath:(UIBezierPath *)bezierPath;
- (void)setLineDash:(const CGFloat *)pattern count:(NSInteger)count phase:(CGFloat)phase;
- (void)getLineDash:(CGFloat *)pattern count:(NSInteger *)count phase:(CGFloat *)phase;
- (BOOL)containsPoint:(CGPoint)point;
- (void)applyTransform:(CGAffineTransform)transform;
@property (nonatomic) CGPathRef CGPath;
@property (nonatomic, readonly) CGPoint currentPoint;
@property (nonatomic) CGFloat lineWidth;
@property (nonatomic) CGLineCap lineCapStyle;
@property (nonatomic) CGLineJoin lineJoinStyle;
@property (nonatomic) CGFloat miterLimit;
@property (nonatomic) CGFloat flatness;
@property (nonatomic) BOOL usesEvenOddFillRule;
@property (readonly, getter=isEmpty) BOOL empty;
@property (nonatomic, readonly) CGRect bounds;
@end
#endif
//
// UIColor.h
// Lottie
//
// Created by Oleksii Pavlovskyi on 2/2/17.
// Copyright © 2017 Airbnb. All rights reserved.
//
#include <TargetConditionals.h>
#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
@interface UIColor : NSObject <NSCopying>
+ (UIColor *)colorWithWhite:(CGFloat)white alpha:(CGFloat)alpha;
+ (UIColor *)colorWithHue:(CGFloat)hue saturation:(CGFloat)saturation brightness:(CGFloat)brightness alpha:(CGFloat)alpha;
+ (UIColor *)colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha;
+ (UIColor *)colorWithCGColor:(CGColorRef)cgColor;
+ (UIColor *)blackColor;
+ (UIColor *)darkGrayColor;
+ (UIColor *)lightGrayColor;
+ (UIColor *)whiteColor;
+ (UIColor *)grayColor;
+ (UIColor *)redColor;
+ (UIColor *)greenColor;
+ (UIColor *)blueColor;
+ (UIColor *)cyanColor;
+ (UIColor *)yellowColor;
+ (UIColor *)magentaColor;
+ (UIColor *)orangeColor;
+ (UIColor *)purpleColor;
+ (UIColor *)brownColor;
+ (UIColor *)clearColor;
- (UIColor *)colorWithAlphaComponent:(CGFloat)alpha;
@property (nonatomic, readonly) CGColorRef CGColor;
@end
#endif
//
// UIColor.m
// Lottie
//
// Created by Oleksii Pavlovskyi on 2/2/17.
// Copyright © 2017 Airbnb. All rights reserved.
//
#include <TargetConditionals.h>
#if !TARGET_OS_IPHONE && !TARGET_OS_SIMULATOR
#import "UIColor.h"
#import <AppKit/AppKit.h>
#define StaticColor(staticColor) \
static UIColor *color = nil; \
static dispatch_once_t onceToken; \
dispatch_once(&onceToken, ^{ \
color = NSColor.staticColor.UIColor; \
}); \
return color; \
@interface UIColor ()
@property (nonatomic, strong) NSColor *color;
- (instancetype)initWithNSColor:(NSColor *)color;
@end
@interface NSColor (UIColor)
@property (nonatomic, readonly) UIColor *UIColor;
@end
@implementation UIColor
- (instancetype)initWithNSColor:(NSColor *)color {
self = [super init];
if (self) {
self.color = color;
}
return self;
}
+ (UIColor *)colorWithNSColor:(NSColor *)color {
return [[self alloc] initWithNSColor:color];
}
+ (UIColor *)colorWithWhite:(CGFloat)white alpha:(CGFloat)alpha {
return [[NSColor colorWithWhite:white alpha:alpha] UIColor];
}
+ (UIColor *)colorWithHue:(CGFloat)hue
saturation:(CGFloat)saturation
brightness:(CGFloat)brightness
alpha:(CGFloat)alpha {
return [[NSColor colorWithHue:hue
saturation:saturation
brightness:brightness
alpha:alpha] UIColor];
}
+ (UIColor *)colorWithRed:(CGFloat)red green:(CGFloat)green blue:(CGFloat)blue alpha:(CGFloat)alpha {
return [[NSColor colorWithRed:red
green:green
blue:blue
alpha:alpha] UIColor];
}
+ (UIColor *)colorWithCGColor:(CGColorRef)cgColor {
return [[NSColor colorWithCGColor:cgColor] UIColor];
}
+ (UIColor *)blackColor {
StaticColor(blackColor)
}
+ (UIColor *)darkGrayColor {
StaticColor(darkGrayColor)
}
+ (UIColor *)lightGrayColor {
StaticColor(lightGrayColor)
}
+ (UIColor *)whiteColor {
StaticColor(whiteColor)
}
+ (UIColor *)grayColor {
StaticColor(grayColor)
}
+ (UIColor *)redColor {
StaticColor(redColor)
}
+ (UIColor *)greenColor {
StaticColor(greenColor)
}
+ (UIColor *)blueColor {
StaticColor(blueColor)
}
+ (UIColor *)cyanColor {
StaticColor(cyanColor)
}
+ (UIColor *)yellowColor {
StaticColor(yellowColor)
}
+ (UIColor *)magentaColor {
StaticColor(magentaColor)
}
+ (UIColor *)orangeColor {
StaticColor(orangeColor)
}
+ (UIColor *)purpleColor {
StaticColor(purpleColor)
}
+ (UIColor *)brownColor {
StaticColor(brownColor)
}
+ (UIColor *)clearColor {
StaticColor(clearColor)
}
- (CGColorRef)CGColor {
return self.color.CGColor;
}
- (UIColor *)colorWithAlphaComponent:(CGFloat)alpha {
return [self.color colorWithAlphaComponent:alpha].UIColor;
}
- (id)copyWithZone:(NSZone *)zone {
return [[self.color copyWithZone:zone] UIColor];
}
@end
@implementation NSColor (UIColor)
- (UIColor *)UIColor {
return [UIColor colorWithNSColor:self];
}
@end
#endif
//
// LOTAsset.h
// Pods
//
// Created by Brandon Withrow on 2/16/17.
//
//
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
NS_ASSUME_NONNULL_BEGIN
@class LOTLayerGroup;
@class LOTLayer;
@class LOTAssetGroup;
@interface LOTAsset : NSObject
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary
withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup
withAssetBundle:(NSBundle *_Nonnull)bundle
withFramerate:(NSNumber *)framerate;
@property (nonatomic, readonly, nullable) NSString *referenceID;
@property (nonatomic, readonly, nullable) NSNumber *assetWidth;
@property (nonatomic, readonly, nullable) NSNumber *assetHeight;
@property (nonatomic, readonly, nullable) NSString *imageName;
@property (nonatomic, readonly, nullable) NSString *imageDirectory;
@property (nonatomic, readonly, nullable) LOTLayerGroup *layerGroup;
@property (nonatomic, readwrite) NSString *rootDirectory;
@property (nonatomic, readonly) NSBundle *assetBundle;
@end
NS_ASSUME_NONNULL_END
//
// LOTAsset.m
// Pods
//
// Created by Brandon Withrow on 2/16/17.
//
//
#import "LOTAsset.h"
#import "LOTLayer.h"
#import "LOTLayerGroup.h"
#import "LOTAssetGroup.h"
@implementation LOTAsset
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary
withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup
withAssetBundle:(NSBundle *_Nonnull)bundle
withFramerate:(NSNumber *)framerate {
self = [super init];
if (self) {
_assetBundle = bundle;
[self _mapFromJSON:jsonDictionary
withAssetGroup:assetGroup
withFramerate:framerate];
}
return self;
}
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary
withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup
withFramerate:(NSNumber *)framerate {
_referenceID = [jsonDictionary[@"id"] copy];
if (jsonDictionary[@"w"]) {
_assetWidth = [jsonDictionary[@"w"] copy];
}
if (jsonDictionary[@"h"]) {
_assetHeight = [jsonDictionary[@"h"] copy];
}
if (jsonDictionary[@"u"]) {
_imageDirectory = [jsonDictionary[@"u"] copy];
}
if (jsonDictionary[@"p"]) {
_imageName = [jsonDictionary[@"p"] copy];
}
NSArray *layersJSON = jsonDictionary[@"layers"];
if (layersJSON) {
_layerGroup = [[LOTLayerGroup alloc] initWithLayerJSON:layersJSON
withAssetGroup:assetGroup
withFramerate:framerate];
}
}
@end
//
// LOTAssetGroup.h
// Pods
//
// Created by Brandon Withrow on 2/17/17.
//
//
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
@class LOTAsset;
@class LOTLayerGroup;
@interface LOTAssetGroup : NSObject
@property (nonatomic, readwrite) NSString * _Nullable rootDirectory;
@property (nonatomic, readonly, nullable) NSBundle *assetBundle;
- (instancetype _Nonnull)initWithJSON:(NSArray * _Nonnull)jsonArray
withAssetBundle:(NSBundle *_Nullable)bundle
withFramerate:(NSNumber * _Nonnull)framerate;
- (void)buildAssetNamed:(NSString * _Nonnull)refID withFramerate:(NSNumber * _Nonnull)framerate;
- (void)finalizeInitializationWithFramerate:(NSNumber * _Nonnull)framerate;
- (LOTAsset * _Nullable)assetModelForID:(NSString * _Nonnull)assetID;
@end
//
// LOTAssetGroup.m
// Pods
//
// Created by Brandon Withrow on 2/17/17.
//
//
#import "LOTAssetGroup.h"
#import "LOTAsset.h"
@implementation LOTAssetGroup {
NSMutableDictionary<NSString *, LOTAsset *> *_assetMap;
NSDictionary<NSString *, NSDictionary *> *_assetJSONMap;
}
- (instancetype _Nonnull)initWithJSON:(NSArray * _Nonnull)jsonArray
withAssetBundle:(NSBundle * _Nullable)bundle
withFramerate:(NSNumber * _Nonnull)framerate {
self = [super init];
if (self) {
_assetBundle = bundle;
_assetMap = [NSMutableDictionary dictionary];
NSMutableDictionary *assetJSONMap = [NSMutableDictionary dictionary];
for (NSDictionary<NSString *, NSString *> *assetDictionary in jsonArray) {
NSString *referenceID = assetDictionary[@"id"];
if (referenceID) {
assetJSONMap[referenceID] = assetDictionary;
}
}
_assetJSONMap = assetJSONMap;
}
return self;
}
- (void)buildAssetNamed:(NSString *)refID
withFramerate:(NSNumber * _Nonnull)framerate {
if ([self assetModelForID:refID]) {
return;
}
NSDictionary *assetDictionary = _assetJSONMap[refID];
if (assetDictionary) {
LOTAsset *asset = [[LOTAsset alloc] initWithJSON:assetDictionary
withAssetGroup:self
withAssetBundle:_assetBundle
withFramerate:framerate];
_assetMap[refID] = asset;
}
}
- (void)finalizeInitializationWithFramerate:(NSNumber * _Nonnull)framerate {
for (NSString *refID in _assetJSONMap.allKeys) {
[self buildAssetNamed:refID withFramerate:framerate];
}
_assetJSONMap = nil;
}
- (LOTAsset *)assetModelForID:(NSString *)assetID {
return _assetMap[assetID];
}
- (void)setRootDirectory:(NSString *)rootDirectory {
_rootDirectory = rootDirectory;
[_assetMap enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, LOTAsset * _Nonnull obj, BOOL * _Nonnull stop) {
obj.rootDirectory = rootDirectory;
}];
}
@end
//
// LOTLayer.h
// LottieAnimator
//
// Created by Brandon Withrow on 12/14/15.
// Copyright © 2015 Brandon Withrow. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "LOTPlatformCompat.h"
#import "LOTKeyframe.h"
@class LOTShapeGroup;
@class LOTMask;
@class LOTAsset;
@class LOTAssetGroup;
typedef enum : NSInteger {
LOTLayerTypePrecomp,
LOTLayerTypeSolid,
LOTLayerTypeImage,
LOTLayerTypeNull,
LOTLayerTypeShape,
LOTLayerTypeUnknown
} LOTLayerType;
typedef enum : NSInteger {
LOTMatteTypeNone,
LOTMatteTypeAdd,
LOTMatteTypeInvert,
LOTMatteTypeUnknown
} LOTMatteType;
NS_ASSUME_NONNULL_BEGIN
@interface LOTLayer : NSObject
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary
withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup
withFramerate:(NSNumber *)framerate;
@property (nonatomic, readonly) NSString *layerName;
@property (nonatomic, readonly, nullable) NSString *referenceID;
@property (nonatomic, readonly) NSNumber *layerID;
@property (nonatomic, readonly) LOTLayerType layerType;
@property (nonatomic, readonly, nullable) NSNumber *parentID;
@property (nonatomic, readonly) NSNumber *startFrame;
@property (nonatomic, readonly) NSNumber *inFrame;
@property (nonatomic, readonly) NSNumber *outFrame;
@property (nonatomic, readonly) NSNumber *timeStretch;
@property (nonatomic, readonly) CGRect layerBounds;
@property (nonatomic, readonly, nullable) NSArray<LOTShapeGroup *> *shapes;
@property (nonatomic, readonly, nullable) NSArray<LOTMask *> *masks;
@property (nonatomic, readonly, nullable) NSNumber *layerWidth;
@property (nonatomic, readonly, nullable) NSNumber *layerHeight;
@property (nonatomic, readonly, nullable) UIColor *solidColor;
@property (nonatomic, readonly, nullable) LOTAsset *imageAsset;
@property (nonatomic, readonly) LOTKeyframeGroup *opacity;
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *timeRemapping;
@property (nonatomic, readonly) LOTKeyframeGroup *rotation;
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *position;
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *positionX;
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *positionY;
@property (nonatomic, readonly) LOTKeyframeGroup *anchor;
@property (nonatomic, readonly) LOTKeyframeGroup *scale;
@property (nonatomic, readonly) LOTMatteType matteType;
@end
NS_ASSUME_NONNULL_END
//
// LOTLayer.m
// LottieAnimator
//
// Created by Brandon Withrow on 12/14/15.
// Copyright © 2015 Brandon Withrow. All rights reserved.
//
#import "LOTLayer.h"
#import "LOTAsset.h"
#import "LOTAssetGroup.h"
#import "LOTShapeGroup.h"
#import "LOTComposition.h"
#import "LOTHelpers.h"
#import "LOTMask.h"
#import "LOTHelpers.h"
@implementation LOTLayer
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary
withAssetGroup:(LOTAssetGroup *)assetGroup
withFramerate:(NSNumber *)framerate {
self = [super init];
if (self) {
[self _mapFromJSON:jsonDictionary
withAssetGroup:assetGroup
withFramerate:framerate];
}
return self;
}
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary
withAssetGroup:(LOTAssetGroup *)assetGroup
withFramerate:(NSNumber *)framerate {
_layerName = [jsonDictionary[@"nm"] copy];
_layerID = [jsonDictionary[@"ind"] copy];
NSNumber *layerType = jsonDictionary[@"ty"];
_layerType = layerType.integerValue;
if (jsonDictionary[@"refId"]) {
_referenceID = [jsonDictionary[@"refId"] copy];
}
_parentID = [jsonDictionary[@"parent"] copy];
if (jsonDictionary[@"st"]) {
_startFrame = [jsonDictionary[@"st"] copy];
}
_inFrame = [jsonDictionary[@"ip"] copy];
_outFrame = [jsonDictionary[@"op"] copy];
if (jsonDictionary[@"sr"]) {
_timeStretch = [jsonDictionary[@"sr"] copy];
} else {
_timeStretch = @1;
}
if (_layerType == LOTLayerTypePrecomp) {
_layerHeight = [jsonDictionary[@"h"] copy];
_layerWidth = [jsonDictionary[@"w"] copy];
[assetGroup buildAssetNamed:_referenceID withFramerate:framerate];
} else if (_layerType == LOTLayerTypeImage) {
[assetGroup buildAssetNamed:_referenceID withFramerate:framerate];
_imageAsset = [assetGroup assetModelForID:_referenceID];
_layerWidth = [_imageAsset.assetWidth copy];
_layerHeight = [_imageAsset.assetHeight copy];
} else if (_layerType == LOTLayerTypeSolid) {
_layerWidth = jsonDictionary[@"sw"];
_layerHeight = jsonDictionary[@"sh"];
NSString *solidColor = jsonDictionary[@"sc"];
_solidColor = [UIColor LOT_colorWithHexString:solidColor];
}
_layerBounds = CGRectMake(0, 0, _layerWidth.floatValue, _layerHeight.floatValue);
NSDictionary *ks = jsonDictionary[@"ks"];
NSDictionary *opacity = ks[@"o"];
if (opacity) {
_opacity = [[LOTKeyframeGroup alloc] initWithData:opacity];
[_opacity remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
return LOT_RemapValue(inValue, 0, 100, 0, 1);
}];
}
NSDictionary *timeRemap = jsonDictionary[@"tm"];
if (timeRemap) {
_timeRemapping = [[LOTKeyframeGroup alloc] initWithData:timeRemap];
[_timeRemapping remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
return inValue * framerate.doubleValue;
}];
}
NSDictionary *rotation = ks[@"r"];
if (rotation == nil) {
rotation = ks[@"rz"];
}
if (rotation) {
_rotation = [[LOTKeyframeGroup alloc] initWithData:rotation];
[_rotation remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
return LOT_DegreesToRadians(inValue);
}];
}
NSDictionary *position = ks[@"p"];
if ([position[@"s"] boolValue]) {
// Separate dimensions
_positionX = [[LOTKeyframeGroup alloc] initWithData:position[@"x"]];
_positionY = [[LOTKeyframeGroup alloc] initWithData:position[@"y"]];
} else {
_position = [[LOTKeyframeGroup alloc] initWithData:position ];
}
NSDictionary *anchor = ks[@"a"];
if (anchor) {
_anchor = [[LOTKeyframeGroup alloc] initWithData:anchor];
}
NSDictionary *scale = ks[@"s"];
if (scale) {
_scale = [[LOTKeyframeGroup alloc] initWithData:scale];
[_scale remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
return LOT_RemapValue(inValue, -100, 100, -1, 1);
}];
}
_matteType = [jsonDictionary[@"tt"] integerValue];
NSMutableArray *masks = [NSMutableArray array];
for (NSDictionary *maskJSON in jsonDictionary[@"masksProperties"]) {
LOTMask *mask = [[LOTMask alloc] initWithJSON:maskJSON];
[masks addObject:mask];
}
_masks = masks.count ? masks : nil;
NSMutableArray *shapes = [NSMutableArray array];
for (NSDictionary *shapeJSON in jsonDictionary[@"shapes"]) {
id shapeItem = [LOTShapeGroup shapeItemWithJSON:shapeJSON];
if (shapeItem) {
[shapes addObject:shapeItem];
}
}
_shapes = shapes;
NSArray *effects = jsonDictionary[@"ef"];
if (effects.count > 0) {
NSDictionary *effectNames = @{ @0: @"slider",
@1: @"angle",
@2: @"color",
@3: @"point",
@4: @"checkbox",
@5: @"group",
@6: @"noValue",
@7: @"dropDown",
@9: @"customValue",
@10: @"layerIndex",
@20: @"tint",
@21: @"fill" };
for (NSDictionary *effect in effects) {
NSNumber *typeNumber = effect[@"ty"];
NSString *name = effect[@"nm"];
NSString *internalName = effect[@"mn"];
NSString *typeString = effectNames[typeNumber];
if (typeString) {
NSLog(@"%s: Warning: %@ effect not supported: %@ / %@", __PRETTY_FUNCTION__, typeString, internalName, name);
}
}
}
}
- (NSString *)description {
NSMutableString *text = [[super description] mutableCopy];
[text appendFormat:@" %@ id: %d pid: %d frames: %d-%d", _layerName, (int)_layerID.integerValue, (int)_parentID.integerValue,
(int)_inFrame.integerValue, (int)_outFrame.integerValue];
return text;
}
@end
//
// LOTLayerGroup.h
// Pods
//
// Created by Brandon Withrow on 2/16/17.
//
//
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
NS_ASSUME_NONNULL_BEGIN
@class LOTLayer;
@class LOTAssetGroup;
@interface LOTLayerGroup : NSObject
- (instancetype)initWithLayerJSON:(NSArray *)layersJSON
withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup
withFramerate:(NSNumber *)framerate;
@property (nonatomic, readonly) NSArray <LOTLayer *> *layers;
- (LOTLayer *)layerModelForID:(NSNumber *)layerID;
- (LOTLayer *)layerForReferenceID:(NSString *)referenceID;
@end
NS_ASSUME_NONNULL_END
//
// LOTLayerGroup.m
// Pods
//
// Created by Brandon Withrow on 2/16/17.
//
//
#import "LOTLayerGroup.h"
#import "LOTLayer.h"
#import "LOTAssetGroup.h"
@implementation LOTLayerGroup {
NSDictionary *_modelMap;
NSDictionary *_referenceIDMap;
}
- (instancetype)initWithLayerJSON:(NSArray *)layersJSON
withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup
withFramerate:(NSNumber *)framerate {
self = [super init];
if (self) {
[self _mapFromJSON:layersJSON withAssetGroup:assetGroup withFramerate:framerate];
}
return self;
}
- (void)_mapFromJSON:(NSArray *)layersJSON
withAssetGroup:(LOTAssetGroup * _Nullable)assetGroup
withFramerate:(NSNumber *)framerate {
NSMutableArray *layers = [NSMutableArray array];
NSMutableDictionary *modelMap = [NSMutableDictionary dictionary];
NSMutableDictionary *referenceMap = [NSMutableDictionary dictionary];
for (NSDictionary *layerJSON in layersJSON) {
LOTLayer *layer = [[LOTLayer alloc] initWithJSON:layerJSON
withAssetGroup:assetGroup
withFramerate:framerate];
[layers addObject:layer];
modelMap[layer.layerID] = layer;
if (layer.referenceID) {
referenceMap[layer.referenceID] = layer;
}
}
_referenceIDMap = referenceMap;
_modelMap = modelMap;
_layers = layers;
}
- (LOTLayer *)layerModelForID:(NSNumber *)layerID {
return _modelMap[layerID];
}
- (LOTLayer *)layerForReferenceID:(NSString *)referenceID {
return _referenceIDMap[referenceID];
}
@end
//
// LOTMask.h
// LottieAnimator
//
// Created by Brandon Withrow on 12/14/15.
// Copyright © 2015 Brandon Withrow. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "LOTKeyframe.h"
typedef enum : NSUInteger {
LOTMaskModeAdd,
LOTMaskModeSubtract,
LOTMaskModeIntersect,
LOTMaskModeUnknown
} LOTMaskMode;
@interface LOTMask : NSObject
- (instancetype _Nonnull)initWithJSON:(NSDictionary * _Nonnull)jsonDictionary;
@property (nonatomic, readonly) BOOL closed;
@property (nonatomic, readonly) BOOL inverted;
@property (nonatomic, readonly) LOTMaskMode maskMode;
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *maskPath;
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *opacity;
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *expansion;
@end
//
// LOTMask.m
// LottieAnimator
//
// Created by Brandon Withrow on 12/14/15.
// Copyright © 2015 Brandon Withrow. All rights reserved.
//
#import "LOTMask.h"
#import "CGGeometry+LOTAdditions.h"
@implementation LOTMask
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary {
self = [super init];
if (self) {
[self _mapFromJSON:jsonDictionary];
}
return self;
}
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary {
NSNumber *closed = jsonDictionary[@"cl"];
_closed = closed.boolValue;
NSNumber *inverted = jsonDictionary[@"inv"];
_inverted = inverted.boolValue;
NSString *mode = jsonDictionary[@"mode"];
if ([mode isEqualToString:@"a"]) {
_maskMode = LOTMaskModeAdd;
} else if ([mode isEqualToString:@"s"]) {
_maskMode = LOTMaskModeSubtract;
} else if ([mode isEqualToString:@"i"]) {
_maskMode = LOTMaskModeIntersect;
} else {
_maskMode = LOTMaskModeUnknown;
}
NSDictionary *maskshape = jsonDictionary[@"pt"];
if (maskshape) {
_maskPath = [[LOTKeyframeGroup alloc] initWithData:maskshape];
}
NSDictionary *opacity = jsonDictionary[@"o"];
if (opacity) {
_opacity = [[LOTKeyframeGroup alloc] initWithData:opacity];
[_opacity remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
return LOT_RemapValue(inValue, 0, 100, 0, 1);
}];
}
NSDictionary *expansion = jsonDictionary[@"x"];
if (expansion) {
_expansion = [[LOTKeyframeGroup alloc] initWithData:expansion];
}
}
@end
//
// LOTModels.h
// LottieAnimator
//
// Created by Brandon Withrow on 12/15/15.
// Copyright © 2015 Brandon Withrow. All rights reserved.
//
#ifndef LOTModels_h
#define LOTModels_h
#import "LOTKeyframe.h"
#import "LOTComposition.h"
#import "LOTLayer.h"
#import "LOTMask.h"
#import "LOTShapeCircle.h"
#import "LOTShapeFill.h"
#import "LOTShapeGroup.h"
#import "LOTShapePath.h"
#import "LOTShapeRectangle.h"
#import "LOTShapeStroke.h"
#import "LOTShapeTransform.h"
#import "LOTShapeTrimPath.h"
#import "LOTLayerGroup.h"
#import "LOTAsset.h"
#import "LOTShapeGradientFill.h"
#endif /* LOTModels_h */
//
// LOTShapeCircle.h
// LottieAnimator
//
// Created by Brandon Withrow on 12/15/15.
// Copyright © 2015 Brandon Withrow. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "LOTKeyframe.h"
NS_ASSUME_NONNULL_BEGIN
@interface LOTShapeCircle : NSObject
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary;
@property (nonatomic, readonly) NSString *keyname;
@property (nonatomic, readonly) LOTKeyframeGroup *position;
@property (nonatomic, readonly) LOTKeyframeGroup *size;
@property (nonatomic, readonly) BOOL reversed;
@end
NS_ASSUME_NONNULL_END
//
// LOTShapeCircle.m
// LottieAnimator
//
// Created by Brandon Withrow on 12/15/15.
// Copyright © 2015 Brandon Withrow. All rights reserved.
//
#import "LOTShapeCircle.h"
@implementation LOTShapeCircle
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary {
self = [super init];
if (self) {
[self _mapFromJSON:jsonDictionary];
}
return self;
}
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary {
if (jsonDictionary[@"nm"] ) {
_keyname = [jsonDictionary[@"nm"] copy];
}
NSDictionary *position = jsonDictionary[@"p"];
if (position) {
_position = [[LOTKeyframeGroup alloc] initWithData:position];
}
NSDictionary *size= jsonDictionary[@"s"];
if (size) {
_size = [[LOTKeyframeGroup alloc] initWithData:size];
}
NSNumber *reversed = jsonDictionary[@"d"];
_reversed = (reversed.integerValue == 3);
}
@end
//
// LOTShapeFill.h
// LottieAnimator
//
// Created by Brandon Withrow on 12/15/15.
// Copyright © 2015 Brandon Withrow. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "LOTKeyframe.h"
NS_ASSUME_NONNULL_BEGIN
@interface LOTShapeFill : NSObject
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary;
@property (nonatomic, readonly) NSString *keyname;
@property (nonatomic, readonly) BOOL fillEnabled;
@property (nonatomic, readonly) LOTKeyframeGroup *color;
@property (nonatomic, readonly) LOTKeyframeGroup *opacity;
@property (nonatomic, readonly) BOOL evenOddFillRule;
@end
NS_ASSUME_NONNULL_END
//
// LOTShapeFill.m
// LottieAnimator
//
// Created by Brandon Withrow on 12/15/15.
// Copyright © 2015 Brandon Withrow. All rights reserved.
//
#import "LOTShapeFill.h"
#import "CGGeometry+LOTAdditions.h"
@implementation LOTShapeFill
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary {
self = [super init];
if (self) {
[self _mapFromJSON:jsonDictionary];
}
return self;
}
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary {
if (jsonDictionary[@"nm"] ) {
_keyname = [jsonDictionary[@"nm"] copy];
}
NSDictionary *color = jsonDictionary[@"c"];
if (color) {
_color = [[LOTKeyframeGroup alloc] initWithData:color];
}
NSDictionary *opacity = jsonDictionary[@"o"];
if (opacity) {
_opacity = [[LOTKeyframeGroup alloc] initWithData:opacity];
[_opacity remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
return LOT_RemapValue(inValue, 0, 100, 0, 1);
}];
}
NSNumber *evenOdd = jsonDictionary[@"r"];
if (evenOdd.integerValue == 2) {
_evenOddFillRule = YES;
} else {
_evenOddFillRule = NO;
}
NSNumber *fillEnabled = jsonDictionary[@"fillEnabled"];
_fillEnabled = fillEnabled.boolValue;
}
@end
//
// LOTShapeGradientFill.h
// Lottie
//
// Created by brandon_withrow on 7/26/17.
// Copyright © 2017 Airbnb. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "LOTKeyframe.h"
NS_ASSUME_NONNULL_BEGIN
typedef enum : NSUInteger {
LOTGradientTypeLinear,
LOTGradientTypeRadial
} LOTGradientType;
@interface LOTShapeGradientFill : NSObject
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary;
@property (nonatomic, readonly) NSString *keyname;
@property (nonatomic, readonly) NSNumber *numberOfColors;
@property (nonatomic, readonly) LOTKeyframeGroup *startPoint;
@property (nonatomic, readonly) LOTKeyframeGroup *endPoint;
@property (nonatomic, readonly) LOTKeyframeGroup *gradient;
@property (nonatomic, readonly) LOTKeyframeGroup *opacity;
@property (nonatomic, readonly) BOOL evenOddFillRule;
@property (nonatomic, readonly) LOTGradientType type;
@end
NS_ASSUME_NONNULL_END
//
// LOTShapeGradientFill.m
// Lottie
//
// Created by brandon_withrow on 7/26/17.
// Copyright © 2017 Airbnb. All rights reserved.
//
#import "LOTShapeGradientFill.h"
#import "CGGeometry+LOTAdditions.h"
@implementation LOTShapeGradientFill
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary {
self = [super init];
if (self) {
[self _mapFromJSON:jsonDictionary];
}
return self;
}
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary {
if (jsonDictionary[@"nm"] ) {
_keyname = [jsonDictionary[@"nm"] copy];
}
NSNumber *type = jsonDictionary[@"t"];
if (type.integerValue != 1) {
_type = LOTGradientTypeRadial;
} else {
_type = LOTGradientTypeLinear;
}
NSDictionary *start = jsonDictionary[@"s"];
if (start) {
_startPoint = [[LOTKeyframeGroup alloc] initWithData:start];
}
NSDictionary *end = jsonDictionary[@"e"];
if (end) {
_endPoint = [[LOTKeyframeGroup alloc] initWithData:end];
}
NSDictionary *gradient = jsonDictionary[@"g"];
if (gradient) {
NSDictionary *unwrappedGradient = gradient[@"k"];
_numberOfColors = gradient[@"p"];
_gradient = [[LOTKeyframeGroup alloc] initWithData:unwrappedGradient];
}
NSDictionary *opacity = jsonDictionary[@"o"];
if (opacity) {
_opacity = [[LOTKeyframeGroup alloc] initWithData:opacity];
[_opacity remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
return LOT_RemapValue(inValue, 0, 100, 0, 1);
}];
}
NSNumber *evenOdd = jsonDictionary[@"r"];
if (evenOdd.integerValue == 2) {
_evenOddFillRule = YES;
} else {
_evenOddFillRule = NO;
}
}
@end
//
// LOTShape.h
// LottieAnimator
//
// Created by Brandon Withrow on 12/14/15.
// Copyright © 2015 Brandon Withrow. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
@interface LOTShapeGroup : NSObject
- (instancetype _Nonnull)initWithJSON:(NSDictionary *_Nonnull)jsonDictionary;
@property (nonatomic, readonly, nonnull) NSString *keyname;
@property (nonatomic, readonly, nonnull) NSArray *items;
+ (id _Nullable)shapeItemWithJSON:(NSDictionary * _Nonnull)itemJSON;
@end
//
// LOTShape.m
// LottieAnimator
//
// Created by Brandon Withrow on 12/14/15.
// Copyright © 2015 Brandon Withrow. All rights reserved.
//
#import "LOTShapeGroup.h"
#import "LOTShapeFill.h"
#import "LOTShapePath.h"
#import "LOTShapeCircle.h"
#import "LOTShapeStroke.h"
#import "LOTShapeTransform.h"
#import "LOTShapeRectangle.h"
#import "LOTShapeTrimPath.h"
#import "LOTShapeGradientFill.h"
#import "LOTShapeStar.h"
#import "LOTShapeRepeater.h"
@implementation LOTShapeGroup
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary {
self = [super init];
if (self) {
[self _mapFromJSON:jsonDictionary];
}
return self;
}
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary {
if (jsonDictionary[@"nm"] ) {
_keyname = [jsonDictionary[@"nm"] copy];
}
NSArray *itemsJSON = jsonDictionary[@"it"];
NSMutableArray *items = [NSMutableArray array];
for (NSDictionary *itemJSON in itemsJSON) {
id newItem = [LOTShapeGroup shapeItemWithJSON:itemJSON];
if (newItem) {
[items addObject:newItem];
}
}
_items = items;
}
+ (id)shapeItemWithJSON:(NSDictionary *)itemJSON {
NSString *type = itemJSON[@"ty"];
if ([type isEqualToString:@"gr"]) {
LOTShapeGroup *group = [[LOTShapeGroup alloc] initWithJSON:itemJSON];
return group;
} else if ([type isEqualToString:@"st"]) {
LOTShapeStroke *stroke = [[LOTShapeStroke alloc] initWithJSON:itemJSON];
return stroke;
} else if ([type isEqualToString:@"fl"]) {
LOTShapeFill *fill = [[LOTShapeFill alloc] initWithJSON:itemJSON];
return fill;
} else if ([type isEqualToString:@"tr"]) {
LOTShapeTransform *transform = [[LOTShapeTransform alloc] initWithJSON:itemJSON];
return transform;
} else if ([type isEqualToString:@"sh"]) {
LOTShapePath *path = [[LOTShapePath alloc] initWithJSON:itemJSON];
return path;
} else if ([type isEqualToString:@"el"]) {
LOTShapeCircle *circle = [[LOTShapeCircle alloc] initWithJSON:itemJSON];
return circle;
} else if ([type isEqualToString:@"rc"]) {
LOTShapeRectangle *rectangle = [[LOTShapeRectangle alloc] initWithJSON:itemJSON];
return rectangle;
} else if ([type isEqualToString:@"tm"]) {
LOTShapeTrimPath *trim = [[LOTShapeTrimPath alloc] initWithJSON:itemJSON];
return trim;
} else if ([type isEqualToString:@"gs"]) {
NSLog(@"%s: Warning: gradient strokes are not supported", __PRETTY_FUNCTION__);
} else if ([type isEqualToString:@"gf"]) {
LOTShapeGradientFill *gradientFill = [[LOTShapeGradientFill alloc] initWithJSON:itemJSON];
return gradientFill;
} else if ([type isEqualToString:@"sr"]) {
LOTShapeStar *star = [[LOTShapeStar alloc] initWithJSON:itemJSON];
return star;
} else if ([type isEqualToString:@"mm"]) {
NSString *name = itemJSON[@"nm"];
NSLog(@"%s: Warning: merge shape is not supported. name: %@", __PRETTY_FUNCTION__, name);
} else if ([type isEqualToString:@"rp"]) {
LOTShapeRepeater *repeater = [[LOTShapeRepeater alloc] initWithJSON:itemJSON];
return repeater;
} else {
NSString *name = itemJSON[@"nm"];
NSLog(@"%s: Unsupported shape: %@ name: %@", __PRETTY_FUNCTION__, type, name);
}
return nil;
}
- (NSString *)description {
NSMutableString *text = [[super description] mutableCopy];
[text appendFormat:@" items: %@", self.items];
return text;
}
@end
//
// LOTShapePath.h
// LottieAnimator
//
// Created by Brandon Withrow on 12/15/15.
// Copyright © 2015 Brandon Withrow. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "LOTKeyframe.h"
@interface LOTShapePath : NSObject
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary;
@property (nonatomic, readonly) NSString *keyname;
@property (nonatomic, readonly) BOOL closed;
@property (nonatomic, readonly) NSNumber *index;
@property (nonatomic, readonly) LOTKeyframeGroup *shapePath;
@end
//
// LOTShapePath.m
// LottieAnimator
//
// Created by Brandon Withrow on 12/15/15.
// Copyright © 2015 Brandon Withrow. All rights reserved.
//
#import "LOTShapePath.h"
@implementation LOTShapePath
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary {
self = [super init];
if (self) {
[self _mapFromJSON:jsonDictionary];
}
return self;
}
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary {
if (jsonDictionary[@"nm"] ) {
_keyname = [jsonDictionary[@"nm"] copy];
}
_index = jsonDictionary[@"ind"];
_closed = [jsonDictionary[@"closed"] boolValue];
NSDictionary *shape = jsonDictionary[@"ks"];
if (shape) {
_shapePath = [[LOTKeyframeGroup alloc] initWithData:shape];
}
}
@end
//
// LOTShapeRectangle.h
// LottieAnimator
//
// Created by Brandon Withrow on 12/15/15.
// Copyright © 2015 Brandon Withrow. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "LOTKeyframe.h"
@interface LOTShapeRectangle : NSObject
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary;
@property (nonatomic, readonly) NSString *keyname;
@property (nonatomic, readonly) LOTKeyframeGroup *position;
@property (nonatomic, readonly) LOTKeyframeGroup *size;
@property (nonatomic, readonly) LOTKeyframeGroup *cornerRadius;
@property (nonatomic, readonly) BOOL reversed;
@end
//
// LOTShapeRectangle.m
// LottieAnimator
//
// Created by Brandon Withrow on 12/15/15.
// Copyright © 2015 Brandon Withrow. All rights reserved.
//
#import "LOTShapeRectangle.h"
@implementation LOTShapeRectangle
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary {
self = [super init];
if (self) {
[self _mapFromJSON:jsonDictionary];
}
return self;
}
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary {
if (jsonDictionary[@"nm"] ) {
_keyname = [jsonDictionary[@"nm"] copy];
}
NSDictionary *position = jsonDictionary[@"p"];
if (position) {
_position = [[LOTKeyframeGroup alloc] initWithData:position];
}
NSDictionary *cornerRadius = jsonDictionary[@"r"];
if (cornerRadius) {
_cornerRadius = [[LOTKeyframeGroup alloc] initWithData:cornerRadius];
}
NSDictionary *size = jsonDictionary[@"s"];
if (size) {
_size = [[LOTKeyframeGroup alloc] initWithData:size];
}
NSNumber *reversed = jsonDictionary[@"d"];
_reversed = (reversed.integerValue == 3);
}
@end
//
// LOTShapeRepeater.h
// Lottie
//
// Created by brandon_withrow on 7/28/17.
// Copyright © 2017 Airbnb. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "LOTKeyframe.h"
NS_ASSUME_NONNULL_BEGIN
@interface LOTShapeRepeater : NSObject
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary;
@property (nonatomic, readonly) NSString *keyname;
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *copies;
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *offset;
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *anchorPoint;
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *scale;
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *position;
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *rotation;
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *startOpacity;
@property (nonatomic, readonly, nullable) LOTKeyframeGroup *endOpacity;
@end
NS_ASSUME_NONNULL_END
//
// LOTShapeRepeater.m
// Lottie
//
// Created by brandon_withrow on 7/28/17.
// Copyright © 2017 Airbnb. All rights reserved.
//
#import "LOTShapeRepeater.h"
#import "CGGeometry+LOTAdditions.h"
@implementation LOTShapeRepeater
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary {
self = [super init];
if (self) {
[self _mapFromJSON:jsonDictionary];
}
return self;
}
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary {
if (jsonDictionary[@"nm"] ) {
_keyname = [jsonDictionary[@"nm"] copy];
}
NSDictionary *copies = jsonDictionary[@"c"];
if (copies) {
_copies = [[LOTKeyframeGroup alloc] initWithData:copies];
}
NSDictionary *offset = jsonDictionary[@"o"];
if (offset) {
_offset = [[LOTKeyframeGroup alloc] initWithData:offset];
}
NSDictionary *transform = jsonDictionary[@"tr"];
NSDictionary *rotation = transform[@"r"];
if (rotation) {
_rotation = [[LOTKeyframeGroup alloc] initWithData:rotation];
[_rotation remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
return LOT_DegreesToRadians(inValue);
}];
}
NSDictionary *startOpacity = transform[@"so"];
if (startOpacity) {
_startOpacity = [[LOTKeyframeGroup alloc] initWithData:startOpacity];
[_startOpacity remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
return LOT_RemapValue(inValue, 0, 100, 0, 1);
}];
}
NSDictionary *endOpacity = transform[@"eo"];
if (endOpacity) {
_endOpacity = [[LOTKeyframeGroup alloc] initWithData:endOpacity];
[_endOpacity remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
return LOT_RemapValue(inValue, 0, 100, 0, 1);
}];
}
NSDictionary *anchorPoint = transform[@"a"];
if (anchorPoint) {
_anchorPoint = [[LOTKeyframeGroup alloc] initWithData:anchorPoint];
}
NSDictionary *position = transform[@"p"];
if (position) {
_position = [[LOTKeyframeGroup alloc] initWithData:position];
}
NSDictionary *scale = transform[@"s"];
if (scale) {
_scale = [[LOTKeyframeGroup alloc] initWithData:scale];
[_scale remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
return LOT_RemapValue(inValue, -100, 100, -1, 1);
}];
}
}
@end
//
// LOTShapeStar.h
// Lottie
//
// Created by brandon_withrow on 7/27/17.
// Copyright © 2017 Airbnb. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "LOTKeyframe.h"
typedef enum : NSUInteger {
LOTPolystarShapeNone,
LOTPolystarShapeStar,
LOTPolystarShapePolygon
} LOTPolystarShape;
@interface LOTShapeStar : NSObject
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary;
@property (nonatomic, readonly) NSString *keyname;
@property (nonatomic, readonly) LOTKeyframeGroup *outerRadius;
@property (nonatomic, readonly) LOTKeyframeGroup *outerRoundness;
@property (nonatomic, readonly) LOTKeyframeGroup *innerRadius;
@property (nonatomic, readonly) LOTKeyframeGroup *innerRoundness;
@property (nonatomic, readonly) LOTKeyframeGroup *position;
@property (nonatomic, readonly) LOTKeyframeGroup *numberOfPoints;
@property (nonatomic, readonly) LOTKeyframeGroup *rotation;
@property (nonatomic, readonly) LOTPolystarShape type;
@end
//
// LOTShapeStar.m
// Lottie
//
// Created by brandon_withrow on 7/27/17.
// Copyright © 2017 Airbnb. All rights reserved.
//
#import "LOTShapeStar.h"
@implementation LOTShapeStar
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary {
self = [super init];
if (self) {
[self _mapFromJSON:jsonDictionary];
}
return self;
}
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary {
if (jsonDictionary[@"nm"] ) {
_keyname = [jsonDictionary[@"nm"] copy];
}
NSDictionary *outerRadius = jsonDictionary[@"or"];
if (outerRadius) {
_outerRadius = [[LOTKeyframeGroup alloc] initWithData:outerRadius];
}
NSDictionary *outerRoundness = jsonDictionary[@"os"];
if (outerRoundness) {
_outerRoundness = [[LOTKeyframeGroup alloc] initWithData:outerRoundness];
}
NSDictionary *innerRadius = jsonDictionary[@"ir"];
if (innerRadius) {
_innerRadius = [[LOTKeyframeGroup alloc] initWithData:innerRadius];
}
NSDictionary *innerRoundness = jsonDictionary[@"is"];
if (innerRoundness) {
_innerRoundness = [[LOTKeyframeGroup alloc] initWithData:innerRoundness];
}
NSDictionary *position = jsonDictionary[@"p"];
if (position) {
_position = [[LOTKeyframeGroup alloc] initWithData:position];
}
NSDictionary *numberOfPoints = jsonDictionary[@"pt"];
if (numberOfPoints) {
_numberOfPoints = [[LOTKeyframeGroup alloc] initWithData:numberOfPoints];
}
NSDictionary *rotation = jsonDictionary[@"r"];
if (rotation) {
_rotation = [[LOTKeyframeGroup alloc] initWithData:rotation];
}
NSNumber *type = jsonDictionary[@"sy"];
_type = type.integerValue;
}
@end
//
// LOTShapeStroke.h
// LottieAnimator
//
// Created by Brandon Withrow on 12/15/15.
// Copyright © 2015 Brandon Withrow. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "LOTKeyframe.h"
typedef enum : NSUInteger {
LOTLineCapTypeButt,
LOTLineCapTypeRound,
LOTLineCapTypeUnknown
} LOTLineCapType;
typedef enum : NSUInteger {
LOTLineJoinTypeMiter,
LOTLineJoinTypeRound,
LOTLineJoinTypeBevel
} LOTLineJoinType;
@interface LOTShapeStroke : NSObject
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary;
@property (nonatomic, readonly) NSString *keyname;
@property (nonatomic, readonly) BOOL fillEnabled;
@property (nonatomic, readonly) LOTKeyframeGroup *color;
@property (nonatomic, readonly) LOTKeyframeGroup *opacity;
@property (nonatomic, readonly) LOTKeyframeGroup *width;
@property (nonatomic, readonly) LOTKeyframeGroup *dashOffset;
@property (nonatomic, readonly) LOTLineCapType capType;
@property (nonatomic, readonly) LOTLineJoinType joinType;
@property (nonatomic, readonly) NSArray *lineDashPattern;
@end
//
// LOTShapeStroke.m
// LottieAnimator
//
// Created by Brandon Withrow on 12/15/15.
// Copyright © 2015 Brandon Withrow. All rights reserved.
//
#import "LOTShapeStroke.h"
#import "CGGeometry+LOTAdditions.h"
@implementation LOTShapeStroke
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary {
self = [super init];
if (self) {
[self _mapFromJSON:jsonDictionary];
}
return self;
}
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary {
if (jsonDictionary[@"nm"] ) {
_keyname = [jsonDictionary[@"nm"] copy];
}
NSDictionary *color = jsonDictionary[@"c"];
if (color) {
_color = [[LOTKeyframeGroup alloc] initWithData:color];
}
NSDictionary *width = jsonDictionary[@"w"];
if (width) {
_width = [[LOTKeyframeGroup alloc] initWithData:width];
}
NSDictionary *opacity = jsonDictionary[@"o"];
if (opacity) {
_opacity = [[LOTKeyframeGroup alloc] initWithData:opacity];
[_opacity remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
return LOT_RemapValue(inValue, 0, 100, 0, 1);
}];
}
_capType = [jsonDictionary[@"lc"] integerValue] - 1;
_joinType = [jsonDictionary[@"lj"] integerValue] - 1;
NSNumber *fillEnabled = jsonDictionary[@"fillEnabled"];
_fillEnabled = fillEnabled.boolValue;
NSDictionary *dashOffset = nil;
NSArray *dashes = jsonDictionary[@"d"];
if (dashes) {
NSMutableArray *dashPattern = [NSMutableArray array];
for (NSDictionary *dash in dashes) {
if ([dash[@"n"] isEqualToString:@"o"]) {
dashOffset = dash[@"v"];
continue;
}
// TODO DASH PATTERNS
NSDictionary *value = dash[@"v"];
LOTKeyframeGroup *keyframeGroup = [[LOTKeyframeGroup alloc] initWithData:value];
[dashPattern addObject:keyframeGroup];
}
_lineDashPattern = dashPattern;
}
if (dashOffset) {
_dashOffset = [[LOTKeyframeGroup alloc] initWithData:dashOffset];
}
}
@end
//
// LOTShapeTransform.h
// LottieAnimator
//
// Created by Brandon Withrow on 12/15/15.
// Copyright © 2015 Brandon Withrow. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <CoreGraphics/CoreGraphics.h>
#import <QuartzCore/QuartzCore.h>
#import "LOTKeyframe.h"
@interface LOTShapeTransform : NSObject
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary;
@property (nonatomic, readonly) NSString *keyname;
@property (nonatomic, readonly) LOTKeyframeGroup *position;
@property (nonatomic, readonly) LOTKeyframeGroup *anchor;
@property (nonatomic, readonly) LOTKeyframeGroup *scale;
@property (nonatomic, readonly) LOTKeyframeGroup *rotation;
@property (nonatomic, readonly) LOTKeyframeGroup *opacity;
@end
//
// LOTShapeTransform.m
// LottieAnimator
//
// Created by Brandon Withrow on 12/15/15.
// Copyright © 2015 Brandon Withrow. All rights reserved.
//
#import "LOTShapeTransform.h"
#import "LOTHelpers.h"
@implementation LOTShapeTransform
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary {
self = [super init];
if (self) {
[self _mapFromJSON:jsonDictionary];
}
return self;
}
- (void)_mapFromJSON:(NSDictionary *)jsonDictionary {
if (jsonDictionary[@"nm"] ) {
_keyname = [jsonDictionary[@"nm"] copy];
}
NSDictionary *position = jsonDictionary[@"p"];
if (position) {
_position = [[LOTKeyframeGroup alloc] initWithData:position];
}
NSDictionary *anchor = jsonDictionary[@"a"];
if (anchor) {
_anchor = [[LOTKeyframeGroup alloc] initWithData:anchor];
}
NSDictionary *scale = jsonDictionary[@"s"];
if (scale) {
_scale = [[LOTKeyframeGroup alloc] initWithData:scale];
[_scale remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
return LOT_RemapValue(inValue, -100, 100, -1, 1);
}];
}
NSDictionary *rotation = jsonDictionary[@"r"];
if (rotation) {
_rotation = [[LOTKeyframeGroup alloc] initWithData:rotation];
[_rotation remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
return LOT_DegreesToRadians(inValue);
}];
}
NSDictionary *opacity = jsonDictionary[@"o"];
if (opacity) {
_opacity = [[LOTKeyframeGroup alloc] initWithData:opacity];
[_opacity remapKeyframesWithBlock:^CGFloat(CGFloat inValue) {
return LOT_RemapValue(inValue, 0, 100, 0, 1);
}];
}
NSString *name = jsonDictionary[@"nm"];
NSDictionary *skew = jsonDictionary[@"sk"];
BOOL hasSkew = (skew && [skew[@"k"] isEqual:@0] == NO);
NSDictionary *skewAxis = jsonDictionary[@"sa"];
BOOL hasSkewAxis = (skewAxis && [skewAxis[@"k"] isEqual:@0] == NO);
if (hasSkew || hasSkewAxis) {
NSLog(@"%s: Warning: skew is not supported: %@", __PRETTY_FUNCTION__, name);
}
}
- (NSString *)description {
return [NSString stringWithFormat:@"LOTShapeTransform \"Position: %@ Anchor: %@ Scale: %@ Rotation: %@ Opacity: %@\"", _position.description, _anchor.description, _scale.description, _rotation.description, _opacity.description];
}
@end
//
// LOTShapeTrimPath.h
// LottieAnimator
//
// Created by brandon_withrow on 7/26/16.
// Copyright © 2016 Brandon Withrow. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "LOTKeyframe.h"
@interface LOTShapeTrimPath : NSObject
- (instancetype)initWithJSON:(NSDictionary *)jsonDictionary;
@property (nonatomic, readonly) NSString *keyname;
@property (nonatomic, readonly) LOTKeyframeGroup *start;
@property (nonatomic, readonly) LOTKeyframeGroup *end;
@property (nonatomic, readonly) LOTKeyframeGroup *offset;
@end
支持 Markdown 格式
你添加了 0 到此讨论。请谨慎行事。
Finish editing this message first!