diff --git a/weex/playground/ios/Podfile b/weex/playground/ios/Podfile index 10e7665..ee5c301 100755 --- a/weex/playground/ios/Podfile +++ b/weex/playground/ios/Podfile @@ -8,6 +8,7 @@ def common pod 'SDWebImage', '3.7.5' pod 'SocketRocket', '0.4.2' pod 'ATSDK-Weex', '0.0.1' + pod 'lottie-ios', '2.5.0' pod 'BindingX', :path=>'../../../' end diff --git a/weex/playground/ios/WeexDemo.xcodeproj/project.pbxproj b/weex/playground/ios/WeexDemo.xcodeproj/project.pbxproj index 2bfdbdb..2d3257b 100644 --- a/weex/playground/ios/WeexDemo.xcodeproj/project.pbxproj +++ b/weex/playground/ios/WeexDemo.xcodeproj/project.pbxproj @@ -33,6 +33,8 @@ D95084AA2046CF9A003F3CC0 /* WXURLResolver.m in Sources */ = {isa = PBXBuildFile; fileRef = D95084A92046CF9A003F3CC0 /* WXURLResolver.m */; }; D95084AD2046CFD0003F3CC0 /* NSString+Additions.m in Sources */ = {isa = PBXBuildFile; fileRef = D95084AC2046CFD0003F3CC0 /* NSString+Additions.m */; }; D95084AF2046D431003F3CC0 /* Launch Screen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = D95084AE2046D431003F3CC0 /* Launch Screen.storyboard */; }; + D9A8959A214B5C3F00AE5DCC /* WXLottieComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = D9A89596214B5C3F00AE5DCC /* WXLottieComponent.m */; }; + D9A8959B214B5C3F00AE5DCC /* WXLottieBindingXHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = D9A89597214B5C3F00AE5DCC /* WXLottieBindingXHandler.m */; }; D9F28AEA207203D100CE451B /* CustomEBHandler.m in Sources */ = {isa = PBXBuildFile; fileRef = D9F28AE9207203D100CE451B /* CustomEBHandler.m */; }; DC5E503E1D0D97130059F0EB /* weex.png in Resources */ = {isa = PBXBuildFile; fileRef = DC5E503C1D0D97130059F0EB /* weex.png */; }; DC5E503F1D0D97130059F0EB /* weex@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = DC5E503D1D0D97130059F0EB /* weex@2x.png */; }; @@ -96,6 +98,10 @@ D95084AB2046CFCF003F3CC0 /* NSString+Additions.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = "NSString+Additions.h"; sourceTree = ""; }; D95084AC2046CFD0003F3CC0 /* NSString+Additions.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "NSString+Additions.m"; sourceTree = ""; }; D95084AE2046D431003F3CC0 /* Launch Screen.storyboard */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; path = "Launch Screen.storyboard"; sourceTree = ""; }; + D9A89596214B5C3F00AE5DCC /* WXLottieComponent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXLottieComponent.m; sourceTree = ""; }; + D9A89597214B5C3F00AE5DCC /* WXLottieBindingXHandler.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXLottieBindingXHandler.m; sourceTree = ""; }; + D9A89598214B5C3F00AE5DCC /* WXLottieComponent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXLottieComponent.h; sourceTree = ""; }; + D9A89599214B5C3F00AE5DCC /* WXLottieBindingXHandler.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXLottieBindingXHandler.h; sourceTree = ""; }; D9F28AE8207203D100CE451B /* CustomEBHandler.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = CustomEBHandler.h; sourceTree = ""; }; D9F28AE9207203D100CE451B /* CustomEBHandler.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = CustomEBHandler.m; sourceTree = ""; }; DC5E503C1D0D97130059F0EB /* weex.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = weex.png; sourceTree = ""; }; @@ -240,12 +246,13 @@ D5ADF0861C77133B00597CA6 /* Source */ = { isa = PBXGroup; children = ( + 2AE88A291C8544D7003329DE /* scanner */, + DCABAFED1D029642001C8592 /* debug */, + D9A89595214B5C3F00AE5DCC /* lottie */, D95084AB2046CFCF003F3CC0 /* NSString+Additions.h */, D95084AC2046CFD0003F3CC0 /* NSString+Additions.m */, D95084A82046CF9A003F3CC0 /* WXURLResolver.h */, D95084A92046CF9A003F3CC0 /* WXURLResolver.m */, - 2AE88A291C8544D7003329DE /* scanner */, - DCABAFED1D029642001C8592 /* debug */, 74CC79E91C2B9E4700829368 /* UIViewController+WXDemoNaviBar.h */, 74CC79EA1C2B9E4700829368 /* UIViewController+WXDemoNaviBar.m */, 775BEE811C1E8ECC008D1629 /* AppDelegate.h */, @@ -261,6 +268,17 @@ name = Source; sourceTree = ""; }; + D9A89595214B5C3F00AE5DCC /* lottie */ = { + isa = PBXGroup; + children = ( + D9A89598214B5C3F00AE5DCC /* WXLottieComponent.h */, + D9A89596214B5C3F00AE5DCC /* WXLottieComponent.m */, + D9A89599214B5C3F00AE5DCC /* WXLottieBindingXHandler.h */, + D9A89597214B5C3F00AE5DCC /* WXLottieBindingXHandler.m */, + ); + path = lottie; + sourceTree = ""; + }; DC65C4421CEB006C00B2F84F /* resource */ = { isa = PBXGroup; children = ( @@ -508,6 +526,7 @@ buildActionMask = 2147483647; files = ( DCABAFF31D029685001C8592 /* WXATLoggerPlugin.m in Sources */, + D9A8959A214B5C3F00AE5DCC /* WXLottieComponent.m in Sources */, D9F28AEA207203D100CE451B /* CustomEBHandler.m in Sources */, 2AE88A2C1C8544E6003329DE /* WXScannerVC.m in Sources */, D95084A72046CE71003F3CC0 /* WXNavigationImpl.m in Sources */, @@ -520,6 +539,7 @@ 775BEE831C1E8ECC008D1629 /* AppDelegate.m in Sources */, DCABAFF41D029685001C8592 /* WXATViewHierarchyPlugin.m in Sources */, 775BEE801C1E8ECC008D1629 /* main.m in Sources */, + D9A8959B214B5C3F00AE5DCC /* WXLottieBindingXHandler.m in Sources */, DCABAFFE1D029753001C8592 /* WXImgLoaderDefaultImpl.m in Sources */, 747DF6681E2F176A005C53A8 /* UIView+UIThreadCheck.m in Sources */, ); diff --git a/weex/playground/ios/WeexDemo/CustomEBHandler.h b/weex/playground/ios/WeexDemo/CustomEBHandler.h index 6ab6f3a..330a0dc 100644 --- a/weex/playground/ios/WeexDemo/CustomEBHandler.h +++ b/weex/playground/ios/WeexDemo/CustomEBHandler.h @@ -1,10 +1,10 @@ -// -// CustomEBHandler.h -// WeexDemo -// -// Created by 对象 on 2018/4/2. -// Copyright © 2018年 taobao. All rights reserved. -// +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ #import #import diff --git a/weex/playground/ios/WeexDemo/CustomEBHandler.m b/weex/playground/ios/WeexDemo/CustomEBHandler.m index 21f6425..087e08e 100644 --- a/weex/playground/ios/WeexDemo/CustomEBHandler.m +++ b/weex/playground/ios/WeexDemo/CustomEBHandler.m @@ -1,10 +1,10 @@ -// -// CustomEBHandler.m -// WeexDemo -// -// Created by 对象 on 2018/4/2. -// Copyright © 2018年 taobao. All rights reserved. -// +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ #import "CustomEBHandler.h" diff --git a/weex/playground/ios/WeexDemo/lottie/WXLottieBindingXHandler.h b/weex/playground/ios/WeexDemo/lottie/WXLottieBindingXHandler.h new file mode 100644 index 0000000..acab314 --- /dev/null +++ b/weex/playground/ios/WeexDemo/lottie/WXLottieBindingXHandler.h @@ -0,0 +1,13 @@ +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ + +#import "EBHandlerFactory.h" + +@interface WXLottieBindingXHandler : NSObject + +@end diff --git a/weex/playground/ios/WeexDemo/lottie/WXLottieBindingXHandler.m b/weex/playground/ios/WeexDemo/lottie/WXLottieBindingXHandler.m new file mode 100644 index 0000000..e6abb00 --- /dev/null +++ b/weex/playground/ios/WeexDemo/lottie/WXLottieBindingXHandler.m @@ -0,0 +1,24 @@ +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ + +#import "WXLottieBindingXHandler.h" +#import "WXLottieComponent.h" + +@implementation WXLottieBindingXHandler + +- (void)execute:(NSDictionary *)properties to:(id)target { + if ([target isKindOfClass:WXLottieComponent.class]) { + id progress = properties[@"lottie-progress"]; + if (progress) { + WXLottieComponent *lottie = (WXLottieComponent *)target; + [lottie setProgress:[WXConvert CGFloat:progress]]; + } + } +} + +@end diff --git a/weex/playground/ios/WeexDemo/lottie/WXLottieComponent.h b/weex/playground/ios/WeexDemo/lottie/WXLottieComponent.h new file mode 100644 index 0000000..1f0b139 --- /dev/null +++ b/weex/playground/ios/WeexDemo/lottie/WXLottieComponent.h @@ -0,0 +1,18 @@ +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ + +#import +#import +#import +#import + +@interface WXLottieComponent : WXComponent + +- (void)setProgress:(CGFloat)progress; + +@end diff --git a/weex/playground/ios/WeexDemo/lottie/WXLottieComponent.m b/weex/playground/ios/WeexDemo/lottie/WXLottieComponent.m new file mode 100644 index 0000000..402f31a --- /dev/null +++ b/weex/playground/ios/WeexDemo/lottie/WXLottieComponent.m @@ -0,0 +1,323 @@ +/** + * Created by Weex. + * Copyright (c) 2016, Alibaba, Inc. All rights reserved. + * + * This source code is licensed under the Apache Licence 2.0. + * For the full copyright and license information,please view the LICENSE file in the root directory of this source tree. + */ + +#import "WXLottieComponent.h" +#import "WXLottieBindingXHandler.h" +#import + +typedef void (^WXLottieCompletionBlock)(void); + +@interface WXLottieView : UIView +@property (nonatomic, assign) BOOL loop; +@property (nonatomic, assign) BOOL autoplay; +@property (nonatomic, assign) CGFloat speed; +@property (nonatomic, assign) CGFloat progress; +@property (nonatomic, strong) NSDictionary *sourcejson; +@property (nonatomic, strong) NSString *sourceName; + +- (void)play:(WXLottieCompletionBlock)completion; +- (void)pause; +- (void)reset; +- (void)setProgress:(CGFloat)progress; +- (void)setValue:(NSString *)keyPath atFrame:(NSNumber *)frame withColor:(UIColor *)color; + +@end + +@implementation WXLottieView +{ + LOTAnimationView *_animationView; +} +- (void)setFrame:(CGRect)frame +{ + [super setFrame:frame]; + if (_animationView != nil) { + [_animationView setFrame:frame]; + } +} + +- (void)play:(WXLottieCompletionBlock)completion +{ + if (_animationView != nil) { + [_animationView playWithCompletion:^(BOOL animationFinished) { + if (completion) { + completion(); + } + }]; + } +} + +- (void)pause +{ + if (_animationView != nil) { + [_animationView pause]; + } +} + +- (void)reset +{ + if (_animationView) { + _animationView.animationProgress = 0; + [_animationView stop]; + } +} + +-(void)setValue:(NSString *)keyPath atFrame:(NSNumber *)frame withColor:(UIColor *)color{ + + if(_animationView != nil){ + // [_animationView setValue:color forKeypath:keyPath atFrame:frame]; + } + +} + +- (void)setProgress:(CGFloat)progress +{ + _progress = progress; + if (_animationView != nil) { + _animationView.animationProgress = progress; + } +} + +- (void)setLoop:(BOOL)loop +{ + _loop = loop; + if (_animationView != nil) { + _animationView.loopAnimation = loop; + } +} + +- (void)setSourceName:(NSString *)src +{ + NSURL * url = [NSURL URLWithString:src]; + if (url.isFileURL) { + // local url + _sourceName = url.path; + [self updateAnimationView:[LOTAnimationView animationNamed:_sourceName]]; + } else { + // remote url + WXResourceRequest * resourceRequest = [WXResourceRequest requestWithURL:url resourceType:WXResourceTypeLink referrer:@"" cachePolicy:NSURLRequestUseProtocolCachePolicy]; + WXResourceLoader * loader = [[WXResourceLoader alloc] initWithRequest:resourceRequest]; + __weak typeof(self) weakSelf = self; + loader.onFinished = ^(const WXResourceResponse * response, NSData * data) { + NSError * error = nil; + NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse*)response; + if (200 == httpResponse.statusCode) { + NSDictionary * dictionary = [WXUtility JSONObject:data error: &error]; + if (error) { + WXLogError(@"convert json object failed with error: %@", error.description); + } + [weakSelf setSourcejson:dictionary]; + } else { + WXLogError(@"server return with status code: %ld", (long)httpResponse.statusCode); + } + }; + + loader.onFailed = ^(NSError * error) { + WXLogError(@"download src %@ failed with error: %@", url, error.description); + }; + + [loader start]; + } +} + +- (void)setSpeed:(CGFloat)speed +{ + _speed = speed; + if (_animationView != nil) { + _animationView.animationSpeed = speed; + } +} + +- (void)setSourcejson:(NSDictionary *)sourcejson +{ + [self updateAnimationView:[LOTAnimationView animationFromJSON:sourcejson]]; +} + +- (void)updateAnimationView:(LOTAnimationView *)newAnimationView +{ + if (_animationView != nil) { + [_animationView removeFromSuperview]; + } + _animationView = newAnimationView; + [self addSubview: newAnimationView]; + [_animationView setFrame:self.bounds]; + [self applyAnimationProperties]; +} + +- (void)applyAnimationProperties +{ + _animationView.animationProgress = _progress; + _animationView.animationSpeed = _speed; + _animationView.loopAnimation = _loop; + if (_autoplay) { + [_animationView play]; + } +} + +@end + +@interface WXLottieComponent() +@property (nonatomic, strong) NSDictionary *sourcejson; +@property (nonatomic) CGFloat progress; +@property (nonatomic) BOOL loop; +@property (nonatomic) BOOL autoplay; +@property (nonatomic) CGFloat speed; +@property (nonatomic, copy) NSString *src; +@property (nonatomic, copy) NSString *resize; +@end + +@implementation WXLottieComponent +WX_PlUGIN_EXPORT_COMPONENT(lottie, WXLottieComponent) +WX_EXPORT_METHOD(@selector(play)) +WX_EXPORT_METHOD(@selector(pause)) +WX_EXPORT_METHOD(@selector(reset)) +WX_EXPORT_METHOD(@selector(setValue:)) +WX_EXPORT_METHOD(@selector(setProgress:)) + +- (instancetype)initWithRef:(NSString *)ref type:(NSString *)type styles:(NSDictionary *)styles attributes:(NSDictionary *)attributes events:(NSArray *)events weexInstance:(WXSDKInstance *)weexInstance +{ + if (self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]) { + _loop = NO; + _sourcejson = nil; + _src = nil; + _progress = 0; + _speed = 1.0; + _autoplay = false; + _resize = @""; + [self fillLottieAttributes:attributes]; + } + + static dispatch_once_t onceToken; + dispatch_once(&onceToken, ^{ + [EBHandlerFactory addHandler:[WXLottieBindingXHandler new]]; + }); + + return self; +} + +- (void)play +{ + if (self.isViewLoaded) { + [(WXLottieView*)self.view play:^() { + [self fireEvent:@"complete" params:nil]; + }]; + } +} + +- (void)pause +{ + if (self.isViewLoaded) { + [(WXLottieView*)self.view pause]; + } +} + +- (void)reset +{ + if (self.isViewLoaded) { + [(WXLottieView*)self.view reset]; + } +} + +- (void)setProgress:(CGFloat)progress +{ + if (self.isViewLoaded) { + [(WXLottieView*)self.view setProgress:progress]; + } +} + +- (void)setValue:(NSDictionary *)options{ + if(self.isViewLoaded){ + if(options[@"keyPath"] && options[@"frame"] && options[@"color"]){ + + NSNumber *frame = @([WXConvert NSInteger:options[@"frame"]]); + NSString *keyPath = [WXConvert NSString:options[@"keyPath"]]; + UIColor *color = [UIColor + colorWithRed: [WXConvert CGFloat:options[@"color"][@"r"]] + green: [WXConvert CGFloat:options[@"color"][@"g"]] + blue: [WXConvert CGFloat:options[@"color"][@"b"]] + alpha: 1.0 + ]; + [(WXLottieView*)self.view setValue:keyPath atFrame:frame withColor:color]; + } + } +} + +- (void)fillLottieAttributes:(NSDictionary*)attributes +{ + if (attributes[@"sourcejson"]) { + if ([attributes[@"sourcejson"] isKindOfClass:NSDictionary.class]) { + _sourcejson = attributes[@"sourcejson"]; + } else if ([attributes[@"sourcejson"] isKindOfClass:NSString.class]) { + _sourcejson = [WXUtility objectFromJSON:attributes[@"sourcejson"]]; + } + } + if (attributes[@"src"]) { + _src = [WXConvert NSString:attributes[@"src"]]; + NSString * newURL = _src; + WX_REWRITE_URL(_src, WXResourceTypeLink, self.weexInstance); + _src = newURL; + } + if (attributes[@"progress"]) { + _progress = [WXConvert CGFloat:attributes[@"progress"]]; + } + if (attributes[@"loop"]) { + _loop = [WXConvert BOOL:attributes[@"loop"]]; + } + if (attributes[@"speed"]) { + _speed = [WXConvert CGFloat:attributes[@"speed"]]; + } + if (attributes[@"autoplay"]) { + _autoplay = [WXConvert BOOL:attributes[@"autoplay"]]; + } + if (attributes[@"resize"]) { + _resize = [attributes[@"resize"] string]; + } +} + +- (void)updateAttributes:(NSDictionary *)attributes +{ + [self fillLottieAttributes:attributes]; + WXLottieView * lottieView = (WXLottieView*)self.view; + if (attributes[@"loop"]) { + [lottieView setLoop:_loop]; + } + if (attributes[@"sourcejson"]) { + [lottieView setSourcejson:_sourcejson]; + } + if (attributes[@"src"]) { + NSString * newURL = _src; + WX_REWRITE_URL(_src, WXResourceTypeLink, self.weexInstance); + _src = newURL; + [lottieView setSourceName:_src]; + } + + if (attributes[@"progress"]) { + [lottieView setProgress:_progress]; + } + if (attributes[@"speed"]) { + [lottieView setSpeed:_speed]; + } +} + +- (void)viewDidLoad +{ + WXLottieView * lottieView = (WXLottieView*)self.view; + + [lottieView setSourceName: _src]; + [lottieView setSpeed:_speed]; + [lottieView setProgress:_progress]; + [lottieView setSourcejson:_sourcejson]; + [lottieView setLoop:_loop]; + [lottieView setAutoplay:_autoplay]; +} + +- (UIView *)loadView +{ + return [WXLottieView new]; +} + +@end