Repository: incubator-weex Updated Branches: refs/heads/0.16-dev 46b98bba9 -> ee94722cf
+ [ios] LayoutAnimation Project: http://git-wip-us.apache.org/repos/asf/incubator-weex/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-weex/commit/6bd86e56 Tree: http://git-wip-us.apache.org/repos/asf/incubator-weex/tree/6bd86e56 Diff: http://git-wip-us.apache.org/repos/asf/incubator-weex/diff/6bd86e56 Branch: refs/heads/0.16-dev Commit: 6bd86e5625bff1310a48244fd2c74db307b9314e Parents: 1ebd484 Author: doumafang <doumaf...@gmail.com> Authored: Tue Aug 8 20:31:03 2017 +0800 Committer: doumafang <doumaf...@gmail.com> Committed: Tue Aug 8 20:31:03 2017 +0800 ---------------------------------------------------------------------- .../Sources/Component/WXComponent_internal.h | 45 +++ .../WeexSDK/Sources/Layout/WXComponent+Layout.m | 281 +++++++++++++++++++ ios/sdk/WeexSDK/Sources/Model/WXComponent.m | 33 ++- .../WeexSDK/Sources/Module/WXAnimationLayout.h | 98 +++---- .../WeexSDK/Sources/Module/WXAnimationLayout.m | 230 +++++++-------- .../WeexSDK/Sources/Module/WXAnimationModule.m | 94 +++++-- 6 files changed, 584 insertions(+), 197 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/6bd86e56/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h index 7226ced..d2b7d54 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h +++ b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h @@ -23,6 +23,8 @@ #import "WXTransform.h" @class WXTouchGestureRecognizer; @class WXThreadSafeCounter; +@class WXLayoutAnimationInfo; + /** * The following variables and methods are used in Weex INTERNAL logic. @@ -42,6 +44,36 @@ CGPoint _absolutePosition; WXPositionType _positionType; + + + //LayoutAnimation + WXLayoutAnimationInfo *_heightInfo; + WXLayoutAnimationInfo *_widthInfo; + WXLayoutAnimationInfo *_topInfo; + WXLayoutAnimationInfo *_rightInfo; + WXLayoutAnimationInfo *_leftInfo; + WXLayoutAnimationInfo *_bottomInfo; + double ax; + double bx; + double cx; + + double ay; + double by; + double cy; + + + float _layoutAnimationDuration; + float _layoutAnimationDelay; + CAMediaTimingFunction *_layoutAnimationTimingFunction; + NSUInteger _layoutAnimationCount; + + NSMutableDictionary *_toStyles; + NSMutableDictionary *_fromStyles; + NSMutableDictionary *_addStyles; + CADisplayLink *_layoutAnimationDisplayLink; + + + /** * View */ @@ -171,6 +203,11 @@ /// @name Private Methods ///-------------------------------------- +- (void)_handleLayoutAnimationWithStyles:(NSDictionary *)styles; + +- (void)_modifyStyles:(NSDictionary *)styles; + + - (void)_initCSSNodeWithStyles:(NSDictionary *)styles; - (void)_updateCSSNodeStyles:(NSDictionary *)styles; @@ -214,3 +251,11 @@ - (void)setGradientLayer; @end + +@interface WXLayoutAnimationInfo : NSObject +@property (nonatomic, strong) id fromValue; +@property (nonatomic, strong) id toValue; +@property (nonatomic, strong) id perValue; +@property (nonatomic, assign) BOOL isAnimated; +@end + http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/6bd86e56/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.m b/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.m index 58e76bf..14034a6 100644 --- a/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.m +++ b/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.m @@ -17,6 +17,9 @@ * under the License. */ +#define SOLVE_EPS(dur) (1. / (1000. * (dur))) + + #import "WXComponent+Layout.h" #import "WXComponent_internal.h" #import "WXTransform.h" @@ -112,6 +115,211 @@ return (int)(count); } + +#pragma mark LayoutAnimationDisplayLink +- (void)_startLayoutAnimationDisplayLink +{ + WXAssertComponentThread(); + if (!_layoutAnimationDisplayLink) { + _layoutAnimationDisplayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(_handleLayoutAnimationDisplayLink)]; + [_layoutAnimationDisplayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode]; + } + else{ + [self _awakeLayoutAnimationDisplayLink]; + } + +} + +- (void)_stopLayoutAnimationDisplayLink +{ + WXAssertComponentThread(); + if (_layoutAnimationDisplayLink) { + [_layoutAnimationDisplayLink invalidate]; + _layoutAnimationDisplayLink = nil; + } +} + +- (void)_suspendLayoutAnimationDisplayLink +{ + WXAssertComponentThread(); + if(_layoutAnimationDisplayLink && !_layoutAnimationDisplayLink.paused) + { + _layoutAnimationDisplayLink.paused = YES; + } +} + + +- (void)_awakeLayoutAnimationDisplayLink +{ + WXAssertComponentThread(); + if (_layoutAnimationDisplayLink && _layoutAnimationDisplayLink.paused) { + _layoutAnimationDisplayLink.paused = NO; + } +} + +- (void)_handleLayoutAnimationDisplayLink +{ + WXAssertComponentThread(); + int count = _layoutAnimationDuration * 60 / 1000; + if (_layoutAnimationCount >= count) { + [self _suspendLayoutAnimationDisplayLink]; + [self _resetProcessAnimationParameter]; + return; + } + else + { + [self _calculateLayoutAnimationProcessingStyle]; + } + _layoutAnimationCount ++; +} + + +- (void)_resetProcessAnimationParameter +{ + + _layoutAnimationCount = 0; + _layoutAnimationDuration = 0; + _widthInfo = nil; + _heightInfo = nil; + _leftInfo = nil; + _rightInfo = nil; + _topInfo = nil; + _bottomInfo = nil; +} + +- (void)_handleLayoutAnimationWithStyles:(NSDictionary *)styles +{ + [self _suspendLayoutAnimationDisplayLink]; + + if (!_addStyles) { + _fromStyles = [NSMutableDictionary dictionaryWithDictionary:self.styles]; + _addStyles = [NSMutableDictionary dictionaryWithDictionary:styles]; + } + else + { + [_addStyles addEntriesFromDictionary:styles]; + }//ä¿è¯_addStylesæ¯å¯ä¸ç + + _toStyles = [NSMutableDictionary dictionaryWithDictionary:_fromStyles]; + [_toStyles addEntriesFromDictionary:_addStyles]; + + _layoutAnimationDuration = _fromStyles[@"transitionDuration"] ? [WXConvert CGFloat:_fromStyles[@"transitionDuration"]] : 0; + _layoutAnimationDelay = _fromStyles[@"transitionDelay"] ? [WXConvert CGFloat:_fromStyles[@"transitionDelay"]] : 0; + _layoutAnimationTimingFunction = [WXConvert CAMediaTimingFunction:_fromStyles[@"transitionTimingFunction"]]; + + + if (_layoutAnimationDuration == 0) { + [self _fillCSSNode:styles]; + return;//å¦æduration为é¶ç´æ¥å ³éå¨ç»ææ + } + + if (![[NSString stringWithFormat:@"%@",_layoutAnimationTimingFunction] isEqualToString: kCAMediaTimingFunctionLinear]) { + float vec[4] = {0.}; + [_layoutAnimationTimingFunction getControlPointAtIndex:1 values:&vec[0]]; + [_layoutAnimationTimingFunction getControlPointAtIndex:2 values:&vec[2]]; + [self unitBezierp1x:vec[0] p1y:vec[1] p2x:vec[2] p2y:vec[3]]; + } + + + NSString *layoutAnimationProperty = _fromStyles[@"transitionProperty"]; + if ([layoutAnimationProperty containsString:@"width"]) { + _widthInfo = [WXLayoutAnimationInfo new]; + _widthInfo.isAnimated = YES; + _widthInfo.fromValue = @(_fromStyles[@"width"] ? [WXConvert CGFloat:_fromStyles[@"width" ]] : 0); + _widthInfo.toValue = @(_toStyles[@"width"] ? [WXConvert CGFloat:_toStyles[@"width"]] : 0 ); + _widthInfo.perValue = @([_widthInfo.toValue doubleValue] - [_widthInfo.fromValue doubleValue]); + + } + if ([layoutAnimationProperty containsString:@"height"]) + { + _heightInfo = [WXLayoutAnimationInfo new]; + _heightInfo.isAnimated = YES; + _heightInfo.fromValue = @(_fromStyles[@"height"] ? [WXConvert CGFloat:_fromStyles[@"height" ]] : 0); + _heightInfo.toValue = @(_toStyles[@"height"] ? [WXConvert CGFloat:_toStyles[@"height"]] : 0 ); + _heightInfo.perValue = @([_heightInfo.toValue doubleValue] - [_heightInfo.fromValue doubleValue]); + + } + if ([layoutAnimationProperty containsString:@"left"]) + { + _leftInfo = [WXLayoutAnimationInfo new]; + _leftInfo.isAnimated = YES; + _leftInfo.fromValue = @(_fromStyles[@"left"] ? [WXConvert CGFloat:_fromStyles[@"left" ]] : 0); + _leftInfo.toValue = @(_toStyles[@"left"] ? [WXConvert CGFloat:_toStyles[@"left"]] : 0 ); + _leftInfo.perValue = @([_leftInfo.toValue doubleValue] - [_leftInfo.fromValue doubleValue]); + + } + if ([layoutAnimationProperty containsString:@"right"]) + { + _rightInfo = [WXLayoutAnimationInfo new]; + _rightInfo.isAnimated = YES; + _rightInfo.fromValue = @(_fromStyles[@"right"] ? [WXConvert CGFloat:_fromStyles[@"right" ]] : 0); + _rightInfo.toValue = @(_toStyles[@"right"] ? [WXConvert CGFloat:_toStyles[@"right"]] : 0 ); + _rightInfo.perValue = @([_rightInfo.toValue doubleValue] - [_rightInfo.fromValue doubleValue]); + + } + if ([layoutAnimationProperty containsString:@"top"]) + { + _topInfo = [WXLayoutAnimationInfo new]; + _topInfo.isAnimated = YES; + _topInfo.fromValue = @(_fromStyles[@"top"] ? [WXConvert CGFloat:_fromStyles[@"top" ]] : 0); + _topInfo.toValue = @(_toStyles[@"top"] ? [WXConvert CGFloat:_toStyles[@"top"]] : 0 ); + _topInfo.perValue = @([_topInfo.toValue doubleValue] - [_topInfo.fromValue doubleValue]); + + } + if ([layoutAnimationProperty containsString:@"bottom"]) + { + _bottomInfo = [WXLayoutAnimationInfo new]; + _bottomInfo.isAnimated = YES; + _bottomInfo.fromValue = @(_fromStyles[@"bottom"] ? [WXConvert CGFloat:_fromStyles[@"bottom" ]] : 0); + _bottomInfo.toValue = @(_toStyles[@"bottom"] ? [WXConvert CGFloat:_toStyles[@"bottom"]] : 0 ); + _bottomInfo.perValue = @([_widthInfo.toValue doubleValue] - [_bottomInfo.fromValue doubleValue]); + + } + if ([layoutAnimationProperty containsString:@"transform"]) { + + + } + + + [self performSelector:@selector(_startLayoutAnimationDisplayLink) withObject:self afterDelay:_layoutAnimationDelay/1000]; + // [self _startLayoutAnimationDisplayLink]; + +} + + +- (void)_calculateLayoutAnimationProcessingStyle +{ + //linear å¨åè´å¡å°æ²çº¿æ¨¡å + double per = 1000 * (_layoutAnimationCount + 1 ) / (60 * _layoutAnimationDuration);//linear + if (![[NSString stringWithFormat:@"%@",_layoutAnimationTimingFunction] isEqualToString: kCAMediaTimingFunctionLinear]) { + per = [self solveWithx:((_layoutAnimationCount+2)*16)/_layoutAnimationDuration epsilon:SOLVE_EPS(_layoutAnimationDuration)]; + } + + double currentWidth = [_widthInfo.fromValue doubleValue] + [_widthInfo.perValue doubleValue] * per; + double currentHeight = [_heightInfo.fromValue doubleValue] + [_heightInfo.perValue doubleValue] * per; + double currentLeft = [_leftInfo.fromValue doubleValue] + [_leftInfo.perValue doubleValue] * per; + double currentRight = [_rightInfo.fromValue doubleValue] + [_rightInfo.perValue doubleValue] * per; + double currentTop = [_topInfo.fromValue doubleValue] + [_topInfo.perValue doubleValue] * per; + double currentBottom = [_bottomInfo.fromValue doubleValue] + [_bottomInfo.perValue doubleValue] * per; + + + + _widthInfo.isAnimated ? [_fromStyles setObject:@(currentWidth) forKey:@"width"]:0; + _heightInfo.isAnimated ? [_fromStyles setObject:@(currentHeight) forKey:@"height"]:0; + _leftInfo.isAnimated ? [_fromStyles setObject:@(currentLeft) forKey:@"left"]:0; + _rightInfo.isAnimated ? [_fromStyles setObject:@(currentRight) forKey:@"right"]:0; + _topInfo.isAnimated ? [_fromStyles setObject:@(currentTop) forKey:@"top"]:0; + _bottomInfo.isAnimated ? [_fromStyles setObject:@(currentBottom) forKey:@"bottom"]:0; + + NSLog(@"%@",_fromStyles); + + [self _fillCSSNode:_fromStyles]; + +} + + + + - (void)_frameDidCalculated:(BOOL)isChanged { WXAssertComponentThread(); @@ -409,4 +617,77 @@ static css_dim_t cssNodeMeasure(void *context, float width, css_measure_mode_t w return (css_dim_t){resultSize.width, resultSize.height}; } +//è´å¡å°æ²çº¿è®¡ç® +- (void)unitBezierp1x:(double)p1x p1y:(double)p1y p2x:(double)p2x p2y:(double)p2y +{ + cx = 3.0 * p1x; + bx = 3.0 * (p2x - p1x) - cx; + ax = 1.0 - cx -bx; + + cy = 3.0 * p1y; + by = 3.0 * (p2y - p1y) - cy; + ay = 1.0 - cy - by; +} +- (double)sampleCurveX:(double)t +{ + return ((ax * t + bx) * t + cx) * t; +} + +- (double)sampleCurveY:(double)t +{ + return ((ay * t + by) * t + cy) * t; +} + +- (double)sampleCurveDerivativeX:(double)t +{ + return (3.0 * ax * t + 2.0 * bx) * t + cx; +} + +- (double)solveCurveX:(double)x epsilon:(double)epsilon +{ + double t0; + double t1; + double t2; + double x2; + double d2; + int i; + + for (t2 = x, i = 0; i < 8; i++) { + x2 = [self sampleCurveX:t2] - x; + if (fabs (x2) < epsilon) + return t2; + d2 = [self sampleCurveDerivativeX:t2]; + if (fabs(d2) < 1e-6) + break; + t2 = t2 - x2 / d2; + } + t0 = 0.0; + t1 = 1.0; + t2 = x; + + if (t2 < t0) + return t0; + if (t2 > t1) + return t1; + + while (t0 < t1) { + x2 = [self sampleCurveX:t2]; + if (fabs(x2 - x) < epsilon) + return t2; + if (x > x2) + t0 = t2; + else + t1 = t2; + t2 = (t1 - t0) * .5 + t0; + } + return t2; +} + +- (double)solveWithx:(double)x epsilon:(double)epsilon +{ + return [self sampleCurveY:([self solveCurveX:x epsilon:epsilon])]; +} + + + @end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/6bd86e56/ios/sdk/WeexSDK/Sources/Model/WXComponent.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m index bd5549b..929d5a5 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m +++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m @@ -436,16 +436,35 @@ - (void)_updateStylesOnComponentThread:(NSDictionary *)styles resetStyles:(NSMutableArray *)resetStyles isUpdateStyles:(BOOL)isUpdateStyles { - if (isUpdateStyles) { - pthread_mutex_lock(&_propertyMutex); - [_styles addEntriesFromDictionary:styles]; - pthread_mutex_unlock(&_propertyMutex); + + //æ ¹æ®å½åçstyleæ¯å¦å«ætransitionPropertyå±æ§æ¥å¤ææ¯å¦æLayout Animation + if (_styles[@"transitionProperty"]) { + [self _handleLayoutAnimationWithStyles:styles]; } - styles = [self parseStyles:styles]; - [self _updateCSSNodeStyles:styles]; + else//å¦æ没æå¨ç»å±æ§æ æ ç´æ¥è§¦ålayout + { + styles = [self parseStyles:styles]; + [self _updateCSSNodeStyles:styles]; + } + + if (isUpdateStyles) { + [self _modifyStyles:styles]; + }//ä¿®æ¹_style + [self _resetCSSNodeStyles:resetStyles]; } +- (void)_modifyStyles:(NSDictionary *)styles //主è¦ç®çæ¯æ¥æ´æ°_style +{ + pthread_mutex_lock(&_propertyMutex); + [_styles addEntriesFromDictionary:styles]; + pthread_mutex_unlock(&_propertyMutex); +} + + + + + - (void)_updateAttributesOnComponentThread:(NSDictionary *)attributes { pthread_mutex_lock(&_propertyMutex); @@ -650,4 +669,6 @@ } @end +@implementation WXLayoutAnimationInfo +@end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/6bd86e56/ios/sdk/WeexSDK/Sources/Module/WXAnimationLayout.h ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Module/WXAnimationLayout.h b/ios/sdk/WeexSDK/Sources/Module/WXAnimationLayout.h index b239c22..1784498 100644 --- a/ios/sdk/WeexSDK/Sources/Module/WXAnimationLayout.h +++ b/ios/sdk/WeexSDK/Sources/Module/WXAnimationLayout.h @@ -1,49 +1,49 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import <Foundation/Foundation.h> - -#import "WXComponent.h" -#import "WXComponent_internal.h" -#import "NSTimer+Weex.h" - -@interface WXAnimationLayoutInfo : NSObject - -@property (nonatomic, strong) NSString *propertyName; -@property (nonatomic, strong) id fromValue; -@property (nonatomic, strong) id toValue; - -@end - - -@interface WXAnimationLayout : NSObject - -@property (nonatomic,strong) NSTimer *updateStyleTimer; -@property (nonatomic,strong) WXComponent *targetComponent; -@property (nonatomic,strong) NSDate *animationStartDate; -@property (nonatomic,strong) WXAnimationLayoutInfo *widthInfo; -@property (nonatomic,strong) WXAnimationLayoutInfo *heightInfo; -@property (nonatomic,assign) double animationDuration; -@property (nonatomic,assign) double animationDelay; -@property (nonatomic,strong) NSDictionary *needUpdateStyles; -@property (nonatomic, weak) WXSDKInstance *weexInstance; - -- (void)layoutForAnimation; - -@end +///* +// * Licensed to the Apache Software Foundation (ASF) under one +// * or more contributor license agreements. See the NOTICE file +// * distributed with this work for additional information +// * regarding copyright ownership. The ASF licenses this file +// * to you under the Apache License, Version 2.0 (the +// * "License"); you may not use this file except in compliance +// * with the License. You may obtain a copy of the License at +// * +// * http://www.apache.org/licenses/LICENSE-2.0 +// * +// * Unless required by applicable law or agreed to in writing, +// * software distributed under the License is distributed on an +// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// * KIND, either express or implied. See the License for the +// * specific language governing permissions and limitations +// * under the License. +// */ +// +//#import <Foundation/Foundation.h> +// +//#import "WXComponent.h" +//#import "WXComponent_internal.h" +//#import "NSTimer+Weex.h" +// +//@interface WXAnimationLayoutInfo : NSObject +// +//@property (nonatomic, strong) NSString *propertyName; +//@property (nonatomic, strong) id fromValue; +//@property (nonatomic, strong) id toValue; +// +//@end +// +// +//@interface WXAnimationLayout : NSObject +// +//@property (nonatomic,strong) NSTimer *updateStyleTimer; +//@property (nonatomic,strong) WXComponent *targetComponent; +//@property (nonatomic,strong) NSDate *animationStartDate; +//@property (nonatomic,strong) WXAnimationLayoutInfo *widthInfo; +//@property (nonatomic,strong) WXAnimationLayoutInfo *heightInfo; +//@property (nonatomic,assign) double animationDuration; +//@property (nonatomic,assign) double animationDelay; +//@property (nonatomic,strong) NSDictionary *needUpdateStyles; +//@property (nonatomic, weak) WXSDKInstance *weexInstance; +// +//- (void)layoutForAnimation; +// +//@end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/6bd86e56/ios/sdk/WeexSDK/Sources/Module/WXAnimationLayout.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Module/WXAnimationLayout.m b/ios/sdk/WeexSDK/Sources/Module/WXAnimationLayout.m index 087135e..341f5d2 100644 --- a/ios/sdk/WeexSDK/Sources/Module/WXAnimationLayout.m +++ b/ios/sdk/WeexSDK/Sources/Module/WXAnimationLayout.m @@ -1,115 +1,115 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ - -#import "WXAnimationLayout.h" -#import "WXSDKInstance_private.h" - -@implementation WXAnimationLayoutInfo - -@end - -@implementation WXAnimationLayout - -- (instancetype)init -{ - if (self = [super init]) { - - } - return self; -} - -- (void)layoutForAnimation -{ - self.animationStartDate = [NSDate date]; - if (_animationDelay > 0) { - [self performSelector:@selector(startUpdateStyleTimer) withObject:nil afterDelay:_animationDelay/1000]; - } else { - [self startUpdateStyleTimer]; - } -} - -#pragma mark UpdateStyle Methods - -- (void)startUpdateStyleTimer -{ - if (!self.updateStyleTimer || ![self.updateStyleTimer isValid]) { - __weak __typeof__(self) weakSelf = self; - self.updateStyleTimer = [NSTimer wx_scheduledTimerWithTimeInterval:16/1000.0f block:^() { - [weakSelf updateStyleOnTimer]; - } repeats:YES]; - [[NSRunLoop currentRunLoop] addTimer:self.updateStyleTimer forMode:NSRunLoopCommonModes]; - } -} - -- (void)stopUpdateStyleTimer -{ - if (self.updateStyleTimer && [self.updateStyleTimer isValid]) { - [self.updateStyleTimer invalidate]; - self.updateStyleTimer = nil; - } -} - -- (void)updateStyleOnTimer -{ - NSTimeInterval startMsecond = [_animationStartDate timeIntervalSince1970]*1000; - NSTimeInterval nowMsecond = [[NSDate date] timeIntervalSince1970]*1000; - NSTimeInterval interval = nowMsecond - startMsecond; - if (!(_widthInfo || _heightInfo)) { - [self stopUpdateStyleTimer]; - return; - } - if (interval > _animationDuration + _animationDelay) { - [self stopUpdateStyleTimer]; - return; - } - CGFloat scaleFactor = self.weexInstance.pixelScaleFactor; - _needUpdateStyles = [[NSMutableDictionary alloc] init]; - if (_widthInfo) { - double currentValue = (([_widthInfo.toValue doubleValue] - [_widthInfo.fromValue doubleValue]) * ((interval - _animationDelay) / _animationDuration) + [_widthInfo.fromValue doubleValue]) / scaleFactor; - [_needUpdateStyles setValue:[NSNumber numberWithDouble:currentValue] forKey:@"width"]; - } - if (_heightInfo) { - double currentValue = (([_heightInfo.toValue doubleValue] - [_heightInfo.fromValue doubleValue]) * ((interval - _animationDelay) / _animationDuration) + [_heightInfo.fromValue doubleValue]) / scaleFactor; - [_needUpdateStyles setValue:[NSNumber numberWithDouble:currentValue] forKey:@"height"]; - } - [self updateStyle:_needUpdateStyles]; -} - -- (void)updateStyle:(NSDictionary *)styles -{ - if ([styles count]>0) { - __weak typeof(self) weakSelf = self; - WXPerformBlockOnComponentThread(^{ - WXComponentManager *manager = weakSelf.weexInstance.componentManager; - if (!manager.isValid) { - return; - } - [manager updateStyles:styles forComponent:_targetComponent.ref]; - [manager startComponentTasks]; - }); - } -} - -- (void)dealloc -{ - [self stopUpdateStyleTimer]; - [NSObject cancelPreviousPerformRequestsWithTarget:self]; -} - -@end +///* +// * Licensed to the Apache Software Foundation (ASF) under one +// * or more contributor license agreements. See the NOTICE file +// * distributed with this work for additional information +// * regarding copyright ownership. The ASF licenses this file +// * to you under the Apache License, Version 2.0 (the +// * "License"); you may not use this file except in compliance +// * with the License. You may obtain a copy of the License at +// * +// * http://www.apache.org/licenses/LICENSE-2.0 +// * +// * Unless required by applicable law or agreed to in writing, +// * software distributed under the License is distributed on an +// * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY +// * KIND, either express or implied. See the License for the +// * specific language governing permissions and limitations +// * under the License. +// */ +// +//#import "WXAnimationLayout.h" +//#import "WXSDKInstance_private.h" +// +//@implementation WXAnimationLayoutInfo +// +//@end +// +//@implementation WXAnimationLayout +// +//- (instancetype)init +//{ +// if (self = [super init]) { +// +// } +// return self; +//} +// +//- (void)layoutForAnimation +//{ +// self.animationStartDate = [NSDate date]; +// if (_animationDelay > 0) { +// [self performSelector:@selector(startUpdateStyleTimer) withObject:nil afterDelay:_animationDelay/1000]; +// } else { +// [self startUpdateStyleTimer]; +// } +//} +// +//#pragma mark UpdateStyle Methods +// +//- (void)startUpdateStyleTimer +//{ +// if (!self.updateStyleTimer || ![self.updateStyleTimer isValid]) { +// __weak __typeof__(self) weakSelf = self; +// self.updateStyleTimer = [NSTimer wx_scheduledTimerWithTimeInterval:16/1000.0f block:^() { +// [weakSelf updateStyleOnTimer]; +// } repeats:YES]; +// [[NSRunLoop currentRunLoop] addTimer:self.updateStyleTimer forMode:NSRunLoopCommonModes]; +// } +//} +// +//- (void)stopUpdateStyleTimer +//{ +// if (self.updateStyleTimer && [self.updateStyleTimer isValid]) { +// [self.updateStyleTimer invalidate]; +// self.updateStyleTimer = nil; +// } +//} +// +//- (void)updateStyleOnTimer +//{ +// NSTimeInterval startMsecond = [_animationStartDate timeIntervalSince1970]*1000; +// NSTimeInterval nowMsecond = [[NSDate date] timeIntervalSince1970]*1000; +// NSTimeInterval interval = nowMsecond - startMsecond; +// if (!(_widthInfo || _heightInfo)) { +// [self stopUpdateStyleTimer]; +// return; +// } +// if (interval > _animationDuration + _animationDelay) { +// [self stopUpdateStyleTimer]; +// return; +// } +// CGFloat scaleFactor = self.weexInstance.pixelScaleFactor; +// _needUpdateStyles = [[NSMutableDictionary alloc] init]; +// if (_widthInfo) { +// double currentValue = (([_widthInfo.toValue doubleValue] - [_widthInfo.fromValue doubleValue]) * ((interval - _animationDelay) / _animationDuration) + [_widthInfo.fromValue doubleValue]) / scaleFactor; +// [_needUpdateStyles setValue:[NSNumber numberWithDouble:currentValue] forKey:@"width"]; +// } +// if (_heightInfo) { +// double currentValue = (([_heightInfo.toValue doubleValue] - [_heightInfo.fromValue doubleValue]) * ((interval - _animationDelay) / _animationDuration) + [_heightInfo.fromValue doubleValue]) / scaleFactor; +// [_needUpdateStyles setValue:[NSNumber numberWithDouble:currentValue] forKey:@"height"]; +// } +// [self updateStyle:_needUpdateStyles]; +//} +// +//- (void)updateStyle:(NSDictionary *)styles +//{ +// if ([styles count]>0) { +// __weak typeof(self) weakSelf = self; +// WXPerformBlockOnComponentThread(^{ +// WXComponentManager *manager = weakSelf.weexInstance.componentManager; +// if (!manager.isValid) { +// return; +// } +// [manager updateStyles:styles forComponent:_targetComponent.ref]; +// [manager startComponentTasks]; +// }); +// } +//} +// +//- (void)dealloc +//{ +// [self stopUpdateStyleTimer]; +// [NSObject cancelPreviousPerformRequestsWithTarget:self]; +//} +// +//@end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/6bd86e56/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m b/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m index 38651e0..46cf68a 100644 --- a/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m +++ b/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m @@ -137,7 +137,7 @@ @interface WXAnimationModule () -@property (nonatomic,strong) WXAnimationLayout *animationLayout; +//@property (nonatomic,strong) WXAnimationLayout *animationLayout; @property (nonatomic,assign) BOOL needLayout; @end @@ -150,8 +150,8 @@ WX_EXPORT_METHOD(@selector(transition:args:callback:)) - (void)transition:(NSString *)nodeRef args:(NSDictionary *)args callback:(WXModuleCallback)callback { _needLayout = NO; - _animationLayout = [[WXAnimationLayout alloc] init]; - _animationLayout.weexInstance = self.weexInstance; +// _animationLayout = [[WXAnimationLayout alloc] init]; +// _animationLayout.weexInstance = self.weexInstance; WXPerformBlockOnComponentThread(^{ WXComponent *targetComponent = [self.weexInstance componentForRef:nodeRef]; if (!targetComponent) { @@ -178,8 +178,8 @@ WX_EXPORT_METHOD(@selector(transition:args:callback:)) if (args[@"needLayout"]) { _needLayout = [WXConvert BOOL:args[@"needLayout"]]; } - _animationLayout.animationDuration = duration * 1000; - _animationLayout.animationDelay = delay * 1000; +// _animationLayout.animationDuration = duration * 1000; +// _animationLayout.animationDelay = delay * 1000; CAMediaTimingFunction *timingFunction = [WXConvert CAMediaTimingFunction:args[@"timingFunction"]]; NSDictionary *styles = args[@"styles"]; for (NSString *property in styles) { @@ -274,30 +274,38 @@ WX_EXPORT_METHOD(@selector(transition:args:callback:)) info.toValue = @([value floatValue]); [infos addObject:info]; } else if ([property isEqualToString:@"width"]) { - info.propertyName = @"bounds.size.width"; - info.fromValue = @(layer.bounds.size.width); - CGRect newBounds = layer.bounds; - newBounds.size = CGSizeMake([WXConvert WXPixelType:value scaleFactor:self.weexInstance.pixelScaleFactor], newBounds.size.height); - info.toValue = @(newBounds.size.width); - [infos addObject:info]; if (_needLayout) { - _animationLayout.widthInfo = [[WXAnimationLayoutInfo alloc] init]; - _animationLayout.widthInfo.toValue = info.toValue; - _animationLayout.widthInfo.fromValue = info.fromValue; - _animationLayout.widthInfo.propertyName = info.propertyName; + [self animationWithLayoutAnimationTarget:target handleProperty:property withDic:args]; + // _animationLayout.widthInfo = [[WXAnimationLayoutInfo alloc] init]; + // _animationLayout.widthInfo.toValue = info.toValue; + // _animationLayout.widthInfo.fromValue = info.fromValue; + // _animationLayout.widthInfo.propertyName = info.propertyName; + } + else + { + info.propertyName = @"bounds.size.width"; + info.fromValue = @(layer.bounds.size.width); + CGRect newBounds = layer.bounds; + newBounds.size = CGSizeMake([WXConvert WXPixelType:value scaleFactor:self.weexInstance.pixelScaleFactor], newBounds.size.height); + info.toValue = @(newBounds.size.width); + [infos addObject:info]; } } else if ([property isEqualToString:@"height"]) { - info.propertyName = @"bounds.size.height"; - info.fromValue = @(layer.bounds.size.height); - CGRect newBounds = layer.bounds; - newBounds.size = CGSizeMake(newBounds.size.width, [WXConvert WXPixelType:value scaleFactor:self.weexInstance.pixelScaleFactor]); - info.toValue = @(newBounds.size.height); - [infos addObject:info]; if (_needLayout) { - _animationLayout.heightInfo = [[WXAnimationLayoutInfo alloc] init]; - _animationLayout.heightInfo.toValue = info.toValue; - _animationLayout.heightInfo.fromValue = info.fromValue; - _animationLayout.heightInfo.propertyName = info.propertyName; + [self animationWithLayoutAnimationTarget:target handleProperty:property withDic:args]; + // _animationLayout.heightInfo = [[WXAnimationLayoutInfo alloc] init]; + // _animationLayout.heightInfo.toValue = info.toValue; + // _animationLayout.heightInfo.fromValue = info.fromValue; + // _animationLayout.heightInfo.propertyName = info.propertyName; + } + else + { + info.propertyName = @"bounds.size.height"; + info.fromValue = @(layer.bounds.size.height); + CGRect newBounds = layer.bounds; + newBounds.size = CGSizeMake(newBounds.size.width, [WXConvert WXPixelType:value scaleFactor:self.weexInstance.pixelScaleFactor]); + info.toValue = @(newBounds.size.height); + [infos addObject:info]; } } } @@ -305,6 +313,35 @@ WX_EXPORT_METHOD(@selector(transition:args:callback:)) return infos; } +- (void)animationWithLayoutAnimationTarget:(WXComponent *)target handleProperty:(NSString *)property withDic:(NSDictionary *)args +{ + NSDictionary *styles = args[@"styles"]; + target->_addStyles = [NSMutableDictionary dictionaryWithDictionary:styles]; + target->_fromStyles = target->_fromStyles ? :[NSMutableDictionary dictionaryWithDictionary:target.styles] ; + [target->_fromStyles setObject:@([args[@"duration"] doubleValue]) forKey:@"transitionDuration"]; + [target->_fromStyles setObject:@([args[@"delay"] doubleValue]) forKey:@"transitionDelay"]; + NSString *oldProperty = target->_fromStyles[@"transitionProperty"]; + NSString *newProperty; + if (oldProperty) { + if ([oldProperty containsString:property]) { + newProperty = oldProperty; + } + else + { + newProperty = [NSString stringWithFormat:@"%@,%@",oldProperty,property]; + } + } + else + { + newProperty = property; + } + [target->_fromStyles setObject:newProperty forKey:@"transitionProperty"]; + [target->_fromStyles setObject:args[@"timingFunction"] forKey:@"transitionTimingFunction"]; + [target _modifyStyles:styles]; + +} + + - (void)animation:(WXComponent *)targetComponent args:(NSDictionary *)args callback:(WXModuleCallback)callback { @@ -327,8 +364,11 @@ WX_EXPORT_METHOD(@selector(transition:args:callback:)) [CATransaction commit]; if (_needLayout) { - _animationLayout.targetComponent = targetComponent; - [_animationLayout layoutForAnimation]; + // _animationLayout.targetComponent = targetComponent; + // [_animationLayout layoutForAnimation]; + WXPerformBlockOnComponentThread(^{ + [targetComponent _handleLayoutAnimationWithStyles:targetComponent->_addStyles]; + }); } }