From 6bd86e5625bff1310a48244fd2c74db307b9314e Mon Sep 17 00:00:00 2001 From: doumafang Date: Tue, 8 Aug 2017 20:31:03 +0800 Subject: [PATCH 1/6] + [ios] LayoutAnimation --- .../Sources/Component/WXComponent_internal.h | 45 +++ .../Sources/Layout/WXComponent+Layout.m | 281 ++++++++++++++++++ ios/sdk/WeexSDK/Sources/Model/WXComponent.m | 33 +- .../Sources/Module/WXAnimationLayout.h | 98 +++--- .../Sources/Module/WXAnimationLayout.m | 230 +++++++------- .../Sources/Module/WXAnimationModule.m | 94 ++++-- 6 files changed, 584 insertions(+), 197 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h index 7226ced0a4..d2b7d54671 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 + diff --git a/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.m b/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.m index 58e76bf057..14034a6d04 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 @@ - (NSUInteger)_childrenCountForLayout 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 diff --git a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m index bd5549bb6f..929d5a547c 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m +++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m @@ -436,16 +436,35 @@ - (void)_moveToSupercomponent:(WXComponent *)newSupercomponent atIndex:(NSUInteg - (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 @@ - (void)setWx_component:(WXComponent *)wx_component } @end +@implementation WXLayoutAnimationInfo +@end diff --git a/ios/sdk/WeexSDK/Sources/Module/WXAnimationLayout.h b/ios/sdk/WeexSDK/Sources/Module/WXAnimationLayout.h index b239c2283d..1784498bc7 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 - -#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 +// +//#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 diff --git a/ios/sdk/WeexSDK/Sources/Module/WXAnimationLayout.m b/ios/sdk/WeexSDK/Sources/Module/WXAnimationLayout.m index 087135ecf5..341f5d2279 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 diff --git a/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m b/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m index 38651e0884..46cf68a363 100644 --- a/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m +++ b/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m @@ -137,7 +137,7 @@ - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag @interface WXAnimationModule () -@property (nonatomic,strong) WXAnimationLayout *animationLayout; +//@property (nonatomic,strong) WXAnimationLayout *animationLayout; @property (nonatomic,assign) BOOL needLayout; @end @@ -150,8 +150,8 @@ @implementation WXAnimationModule - (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 @@ - (void)transition:(NSString *)nodeRef args:(NSDictionary *)args callback:(WXMod 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 @@ - (void)transition:(NSString *)nodeRef args:(NSDictionary *)args callback:(WXMod 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 @@ - (void)transition:(NSString *)nodeRef args:(NSDictionary *)args callback:(WXMod 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 @@ - (void)animation:(WXComponent *)targetComponent args:(NSDictionary *)args callb [CATransaction commit]; if (_needLayout) { - _animationLayout.targetComponent = targetComponent; - [_animationLayout layoutForAnimation]; + // _animationLayout.targetComponent = targetComponent; + // [_animationLayout layoutForAnimation]; + WXPerformBlockOnComponentThread(^{ + [targetComponent _handleLayoutAnimationWithStyles:targetComponent->_addStyles]; + }); } } From 741ee207ec66508d9124cb99a88e530a1458733f Mon Sep 17 00:00:00 2001 From: doumafang Date: Thu, 10 Aug 2017 21:34:48 +0800 Subject: [PATCH 2/6] * [ios] WXTransition --- .../Sources/Component/WXComponent_internal.h | 38 +-- .../Sources/Layout/WXComponent+Layout.m | 280 ---------------- ios/sdk/WeexSDK/Sources/Model/WXComponent.m | 34 +- .../Sources/Module/WXAnimationLayout.h | 49 --- .../Sources/Module/WXAnimationLayout.m | 115 ------- .../Sources/Module/WXAnimationModule.h | 2 + .../Sources/Module/WXAnimationModule.m | 46 ++- ios/sdk/WeexSDK/Sources/Module/WXTransition.h | 38 +++ ios/sdk/WeexSDK/Sources/Module/WXTransition.m | 299 ++++++++++++++++++ 9 files changed, 380 insertions(+), 521 deletions(-) delete mode 100644 ios/sdk/WeexSDK/Sources/Module/WXAnimationLayout.h delete mode 100644 ios/sdk/WeexSDK/Sources/Module/WXAnimationLayout.m create mode 100644 ios/sdk/WeexSDK/Sources/Module/WXTransition.h create mode 100644 ios/sdk/WeexSDK/Sources/Module/WXTransition.m diff --git a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h index d2b7d54671..49db7a9331 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h +++ b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h @@ -21,9 +21,9 @@ #import "WXComponent.h" #import "WXConvert.h" #import "WXTransform.h" +#import "WXTransition.h" @class WXTouchGestureRecognizer; @class WXThreadSafeCounter; -@class WXLayoutAnimationInfo; /** @@ -45,34 +45,8 @@ 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; - - + //Transition + WXTransition *_transition; /** * View @@ -252,10 +226,4 @@ @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 diff --git a/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.m b/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.m index 14034a6d04..4eb57f51b8 100644 --- a/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.m +++ b/ios/sdk/WeexSDK/Sources/Layout/WXComponent+Layout.m @@ -17,8 +17,6 @@ * under the License. */ -#define SOLVE_EPS(dur) (1. / (1000. * (dur))) - #import "WXComponent+Layout.h" #import "WXComponent_internal.h" @@ -116,210 +114,6 @@ - (NSUInteger)_childrenCountForLayout } -#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(); @@ -616,78 +410,4 @@ 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 diff --git a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m index 929d5a547c..b8ae7897ea 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m +++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m @@ -436,12 +436,13 @@ - (void)_moveToSupercomponent:(WXComponent *)newSupercomponent atIndex:(NSUInteg - (void)_updateStylesOnComponentThread:(NSDictionary *)styles resetStyles:(NSMutableArray *)resetStyles isUpdateStyles:(BOOL)isUpdateStyles { - - //根据当前的style是否含有transitionProperty属性来判断是否有Layout Animation - if (_styles[@"transitionProperty"]) { - [self _handleLayoutAnimationWithStyles:styles]; + if ([self _isPropertyTransition]) { + if (!_transition) { + _transition = [WXTransition new]; + } + [_transition _handleTransitionWithStyles:styles withTarget:self]; } - else//如果没有动画属性标明 直接触发layout + else { styles = [self parseStyles:styles]; [self _updateCSSNodeStyles:styles]; @@ -449,22 +450,30 @@ - (void)_updateStylesOnComponentThread:(NSDictionary *)styles resetStyles:(NSMut if (isUpdateStyles) { [self _modifyStyles:styles]; - }//修改_style + } [self _resetCSSNodeStyles:resetStyles]; } -- (void)_modifyStyles:(NSDictionary *)styles //主要目的是来更新_style +- (BOOL)_isPropertyTransition +{ + BOOL yesOrNo = false; + NSString *property = _styles[@"transitionProperty"]; + if (property) { + if ([property containsString:@"width"]||[property containsString:@"height"]||[property containsString:@"top"]||[property containsString:@"left"]||[property containsString:@"bottom"]||[property containsString:@"transform"]) { + yesOrNo = true; + } + } + return yesOrNo; +} + +- (void)_modifyStyles:(NSDictionary *)styles { pthread_mutex_lock(&_propertyMutex); [_styles addEntriesFromDictionary:styles]; pthread_mutex_unlock(&_propertyMutex); } - - - - - (void)_updateAttributesOnComponentThread:(NSDictionary *)attributes { pthread_mutex_lock(&_propertyMutex); @@ -669,6 +678,3 @@ - (void)setWx_component:(WXComponent *)wx_component } @end -@implementation WXLayoutAnimationInfo - -@end diff --git a/ios/sdk/WeexSDK/Sources/Module/WXAnimationLayout.h b/ios/sdk/WeexSDK/Sources/Module/WXAnimationLayout.h deleted file mode 100644 index 1784498bc7..0000000000 --- a/ios/sdk/WeexSDK/Sources/Module/WXAnimationLayout.h +++ /dev/null @@ -1,49 +0,0 @@ -///* -// * 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 -// -//#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 diff --git a/ios/sdk/WeexSDK/Sources/Module/WXAnimationLayout.m b/ios/sdk/WeexSDK/Sources/Module/WXAnimationLayout.m deleted file mode 100644 index 341f5d2279..0000000000 --- a/ios/sdk/WeexSDK/Sources/Module/WXAnimationLayout.m +++ /dev/null @@ -1,115 +0,0 @@ -///* -// * 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 diff --git a/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.h b/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.h index ae7f068550..d5a8c439e1 100644 --- a/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.h +++ b/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.h @@ -22,6 +22,8 @@ @interface WXAnimationModule : NSObject + - (void)animation:(WXComponent *)targetComponent args:(NSDictionary *)args callback:(WXModuleCallback)callback; +- (void)animationModuleProcessAnimationWithArgs:(NSDictionary *)args withWeexInstance:(WXSDKInstance *)instance targetComponent:(WXComponent *)target; @end diff --git a/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m b/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m index 46cf68a363..dc01af3a05 100644 --- a/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m +++ b/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m @@ -24,7 +24,7 @@ #import "WXTransform.h" #import "WXUtility.h" #import "WXLength.h" -#import "WXAnimationLayout.h" +#import "WXTransition.h" @interface WXAnimationInfo : NSObject @@ -36,7 +36,6 @@ @interface WXAnimationInfo : NSObject @property (nonatomic, assign) double delay; @property (nonatomic, strong) CAMediaTimingFunction *timingFunction; @property (nonatomic, assign) CGPoint originAnchorPoint; - @end @implementation WXAnimationInfo @@ -137,8 +136,9 @@ - (void)animationDidStop:(CAAnimation *)anim finished:(BOOL)flag @interface WXAnimationModule () -//@property (nonatomic,strong) WXAnimationLayout *animationLayout; @property (nonatomic,assign) BOOL needLayout; +@property (nonatomic, strong) WXTransition *transition; + @end @implementation WXAnimationModule @@ -150,8 +150,6 @@ @implementation WXAnimationModule - (void)transition:(NSString *)nodeRef args:(NSDictionary *)args callback:(WXModuleCallback)callback { _needLayout = NO; -// _animationLayout = [[WXAnimationLayout alloc] init]; -// _animationLayout.weexInstance = self.weexInstance; WXPerformBlockOnComponentThread(^{ WXComponent *targetComponent = [self.weexInstance componentForRef:nodeRef]; if (!targetComponent) { @@ -177,9 +175,8 @@ - (void)transition:(NSString *)nodeRef args:(NSDictionary *)args callback:(WXMod double delay = [args[@"delay"] doubleValue] / 1000; if (args[@"needLayout"]) { _needLayout = [WXConvert BOOL:args[@"needLayout"]]; + _transition = [WXTransition new]; } -// _animationLayout.animationDuration = duration * 1000; -// _animationLayout.animationDelay = delay * 1000; CAMediaTimingFunction *timingFunction = [WXConvert CAMediaTimingFunction:args[@"timingFunction"]]; NSDictionary *styles = args[@"styles"]; for (NSString *property in styles) { @@ -276,10 +273,6 @@ - (void)transition:(NSString *)nodeRef args:(NSDictionary *)args callback:(WXMod } else if ([property isEqualToString:@"width"]) { if (_needLayout) { [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 { @@ -293,10 +286,6 @@ - (void)transition:(NSString *)nodeRef args:(NSDictionary *)args callback:(WXMod } else if ([property isEqualToString:@"height"]) { if (_needLayout) { [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 { @@ -313,14 +302,20 @@ - (void)transition:(NSString *)nodeRef args:(NSDictionary *)args callback:(WXMod return infos; } +- (void)animationModuleProcessAnimationWithArgs:(NSDictionary *)args withWeexInstance:(WXSDKInstance *)instance targetComponent:(WXComponent *)target +{ + self.weexInstance = instance; + [self animation:target args:args callback:nil]; +} + - (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"]; + _transition.addStyles = [NSMutableDictionary dictionaryWithDictionary:styles]; + _transition.fromStyles =_transition.fromStyles ? :[NSMutableDictionary dictionaryWithDictionary:target.styles] ; + [_transition.fromStyles setObject:@([args[@"duration"] doubleValue]) forKey:@"transitionDuration"]; + [_transition.fromStyles setObject:@([args[@"delay"] doubleValue]) forKey:@"transitionDelay"]; + NSString *oldProperty = _transition.fromStyles[@"transitionProperty"]; NSString *newProperty; if (oldProperty) { if ([oldProperty containsString:property]) { @@ -335,14 +330,11 @@ - (void)animationWithLayoutAnimationTarget:(WXComponent *)target handleProperty: { newProperty = property; } - [target->_fromStyles setObject:newProperty forKey:@"transitionProperty"]; - [target->_fromStyles setObject:args[@"timingFunction"] forKey:@"transitionTimingFunction"]; + [_transition.fromStyles setObject:newProperty forKey:@"transitionProperty"]; + [_transition.fromStyles setObject:args[@"timingFunction"] forKey:@"transitionTimingFunction"]; [target _modifyStyles:styles]; } - - - - (void)animation:(WXComponent *)targetComponent args:(NSDictionary *)args callback:(WXModuleCallback)callback { /** @@ -364,10 +356,8 @@ - (void)animation:(WXComponent *)targetComponent args:(NSDictionary *)args callb [CATransaction commit]; if (_needLayout) { - // _animationLayout.targetComponent = targetComponent; - // [_animationLayout layoutForAnimation]; WXPerformBlockOnComponentThread(^{ - [targetComponent _handleLayoutAnimationWithStyles:targetComponent->_addStyles]; + [_transition _handleTransitionWithStyles:_transition.addStyles withTarget:targetComponent]; }); } } diff --git a/ios/sdk/WeexSDK/Sources/Module/WXTransition.h b/ios/sdk/WeexSDK/Sources/Module/WXTransition.h new file mode 100644 index 0000000000..9a0d5a8d6a --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Module/WXTransition.h @@ -0,0 +1,38 @@ +/* + * 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 + +@interface WXLayoutAnimationInfo : NSObject +@property (nonatomic, strong) id fromValue; +@property (nonatomic, strong) id toValue; +@property (nonatomic, strong) id perValue; +@property (nonatomic, strong) NSString *propertyName; + +@end + +@interface WXTransition : NSObject +@property(nonatomic,strong) NSMutableDictionary *fromStyles; +@property(nonatomic,strong) NSMutableDictionary *addStyles; +@property(nonatomic,strong) NSMutableArray *propertyArray; +- (void)_handleTransitionWithStyles:(NSDictionary *)styles withTarget:(WXComponent *)targetComponent; + +@end + + diff --git a/ios/sdk/WeexSDK/Sources/Module/WXTransition.m b/ios/sdk/WeexSDK/Sources/Module/WXTransition.m new file mode 100644 index 0000000000..26d9fb9fc7 --- /dev/null +++ b/ios/sdk/WeexSDK/Sources/Module/WXTransition.m @@ -0,0 +1,299 @@ +/* + * 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. + */ + +#define SOLVE_EPS(dur) (1. / (1000. * (dur))) + +#import +#import +#import "WXAnimationModule.h" +#import "WXComponentManager.h" +#import "WXSDKInstance.h" +#import "WXComponent+Layout.h" +#import "WXComponent_internal.h" +#import "WXTransition.h" +#import "WXUtility.h" +#import "WXAssert.h" +#import "WXSDKInstance_private.h" + +@implementation WXLayoutAnimationInfo + +@end + +@interface WXTransition() +{ + WXComponent *_targetComponent; + + double ax; + double bx; + double cx; + + double ay; + double by; + double cy; + + float _layoutAnimationDuration; + float _layoutAnimationDelay; + NSUInteger _layoutAnimationCount; + + CAMediaTimingFunction *_layoutAnimationTimingFunction; + CADisplayLink *_layoutAnimationDisplayLink; + + NSMutableDictionary *_toStyles; + NSMutableDictionary *_fromStyles; + NSMutableDictionary *_addStyles; +} + +@end + +@implementation WXTransition + +- (void)_handleTransitionWithStyles:(NSDictionary *)styles withTarget:(WXComponent *)targetComponent +{ + [self _suspendLayoutAnimationDisplayLink]; + _targetComponent = targetComponent; + if (!_addStyles) { + _fromStyles = [NSMutableDictionary dictionaryWithDictionary:targetComponent.styles]; + _addStyles = [NSMutableDictionary dictionaryWithDictionary:styles]; + } + else + { + [_addStyles addEntriesFromDictionary:styles]; + } + + _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) { + [targetComponent _updateCSSNodeStyles:styles]; + WXPerformBlockOnMainThread(^{ + [targetComponent _updateViewStyles:styles]; + }); + return; + } + + 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"]; + [self _resloveTransitionProperty:layoutAnimationProperty withStyles:styles]; + [self performSelector:@selector(_startLayoutAnimationDisplayLink) withObject:self afterDelay:_layoutAnimationDelay/1000]; +} + +- (void)_resloveTransitionProperty:(NSString *)propertyNames withStyles:(NSDictionary *)styles +{ + NSArray *array = @[@"width",@"height",@"top",@"bottom",@"right",@"left",@"transform",@"backgroundColor",@"opacity"]; + for (NSString *propertyName in array) { + if ([propertyNames containsString:propertyName]) { + [self _judgeProperty:propertyName withStyles:styles]; + } + } +} + +- (void)_judgeProperty:(NSString *)singleProperty withStyles:(NSDictionary *)styles +{ + if (([singleProperty isEqualToString:@"transform"]&&styles[@"transform"]) || ([singleProperty containsString:@"backgroundColor"]&&styles[@"backgroundColor"]) || ([singleProperty containsString:@"opacity"]&&styles[@"opacity"])) { + NSDictionary *args = @{@"delay":@(_layoutAnimationDelay),@"duration":@(_layoutAnimationDuration),@"styles":styles,@"timingFunction":_fromStyles[@"transitionTimingFunction"]}; + [self _animationModuleHandleTransition:args]; + } + else{ + WXLayoutAnimationInfo *info = [WXLayoutAnimationInfo new]; + info.fromValue = @(_fromStyles[singleProperty] ? [WXConvert CGFloat:_fromStyles[singleProperty]] : 0); + info.toValue = @(_toStyles[singleProperty] ? [WXConvert CGFloat:_toStyles[singleProperty]] : 0 ); + info.perValue = @([info.toValue doubleValue] - [info.fromValue doubleValue]); + info.propertyName = singleProperty; + if (!_propertyArray) { + _propertyArray = [NSMutableArray new]; + } + [_propertyArray addObject:info]; + } +} + +- (void)_calculateLayoutAnimationProcessingStyle +{ + 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)]; + } + for (WXLayoutAnimationInfo *info in _propertyArray) { + double currentValue = [info.fromValue doubleValue] + [info.perValue doubleValue] * per; + [_fromStyles setObject:@(currentValue) forKey:info.propertyName]; + } + [_targetComponent _updateCSSNodeStyles:_fromStyles]; + [_targetComponent.weexInstance.componentManager startComponentTasks]; +} + +- (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; + +} + +- (void)_animationModuleHandleTransition:(NSDictionary *)args +{ + WXAnimationModule *animation = [WXAnimationModule new]; + WXPerformBlockOnMainThread(^{ + [animation animationModuleProcessAnimationWithArgs:args withWeexInstance:_targetComponent.weexInstance targetComponent:_targetComponent]; + }); +} + +- (NSMutableDictionary *)_addStyles +{ + return self.addStyles; +} + +- (NSMutableDictionary *)_fromStyles +{ + return self.fromStyles; +} + +- (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 From 02658e32eead9f35e9dbe6b877bc9c8d06c08143 Mon Sep 17 00:00:00 2001 From: doumafang Date: Fri, 11 Aug 2017 10:33:26 +0800 Subject: [PATCH 3/6] * [ios] WXTransition fix bugs about how to deal with property --- ios/sdk/WeexSDK/Sources/Model/WXComponent.m | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m index b8ae7897ea..669603f01e 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m +++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m @@ -460,13 +460,27 @@ - (BOOL)_isPropertyTransition BOOL yesOrNo = false; NSString *property = _styles[@"transitionProperty"]; if (property) { - if ([property containsString:@"width"]||[property containsString:@"height"]||[property containsString:@"top"]||[property containsString:@"left"]||[property containsString:@"bottom"]||[property containsString:@"transform"]) { + if ([property containsString:@"width"]||[property containsString:@"height"]||[property containsString:@"top"]||[property containsString:@"bottom"]||[property containsString:@"right"]||[property containsString:@"left"]||[property containsString:@"transform"]||[property containsString:@"backgroundColor"]||[property containsString:@"opacity"]) { yesOrNo = true; } } return yesOrNo; } + +- (BOOL)_isPropertyAnimation +{ + BOOL yesOrNo = false; + NSString *property = _styles[@"transitionProperty"]; + if (property) { + if ([property containsString:@"transform"]||[property containsString:@"backgroundColor"]||[property containsString:@"opacity"]) { + yesOrNo = true; + } + } + return yesOrNo; +} + + - (void)_modifyStyles:(NSDictionary *)styles { pthread_mutex_lock(&_propertyMutex); @@ -498,7 +512,9 @@ - (void)_removeEventOnComponentThread:(NSString *)eventName - (void)_updateStylesOnMainThread:(NSDictionary *)styles resetStyles:(NSMutableArray *)resetStyles { WXAssertMainThread(); - [self _updateViewStyles:styles]; + if (![self _isPropertyAnimation]) { + [self _updateViewStyles:styles]; + } [self _resetStyles:resetStyles]; [self _handleBorders:styles isUpdating:YES]; From 4a3a78092756f9229b6840d70db6b602d7fdf1fd Mon Sep 17 00:00:00 2001 From: doumafang Date: Fri, 11 Aug 2017 18:13:56 +0800 Subject: [PATCH 4/6] * [ios] fix transitionProperty:backgroundColor bug --- .../Sources/Component/WXComponent_internal.h | 1 - .../Sources/Display/WXComponent+Display.m | 16 +++++- ios/sdk/WeexSDK/Sources/Model/WXComponent.m | 30 ++++++---- .../Sources/Module/WXAnimationModule.m | 10 ++-- ios/sdk/WeexSDK/Sources/Module/WXTransition.h | 5 ++ ios/sdk/WeexSDK/Sources/Module/WXTransition.m | 56 +++++++++++-------- 6 files changed, 77 insertions(+), 41 deletions(-) diff --git a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h index 49db7a9331..1e11f4f6b5 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h +++ b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h @@ -181,7 +181,6 @@ - (void)_modifyStyles:(NSDictionary *)styles; - - (void)_initCSSNodeWithStyles:(NSDictionary *)styles; - (void)_updateCSSNodeStyles:(NSDictionary *)styles; diff --git a/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m b/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m index 57594de779..5d22939d82 100644 --- a/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m +++ b/ios/sdk/WeexSDK/Sources/Display/WXComponent+Display.m @@ -553,9 +553,23 @@ - (void)_handleBorders:(NSDictionary *)styles isUpdating:(BOOL)updating [self _resetNativeBorderRadius]; _layer.borderWidth = _borderTopWidth; _layer.borderColor = _borderTopColor.CGColor; - _layer.backgroundColor = _backgroundColor.CGColor; + if (![self _isTransitionBackgroundColorStyles:styles]) { + _layer.backgroundColor = _backgroundColor.CGColor; + } + } + } +} + +- (BOOL)_isTransitionBackgroundColorStyles:(NSDictionary *)styles +{ + BOOL yesOrNo = false; + NSString *property = self.styles[kWXTransitionProperty]; + if (property) { + if (([property containsString:@"backgroundColor"])) { + yesOrNo = true; } } + return yesOrNo; } - (BOOL)_bitmapOpaqueWithSize:(CGSize)size diff --git a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m index 669603f01e..124b769cbc 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m +++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m @@ -433,10 +433,9 @@ - (void)_moveToSupercomponent:(WXComponent *)newSupercomponent atIndex:(NSUInteg } #pragma mark Updating - - (void)_updateStylesOnComponentThread:(NSDictionary *)styles resetStyles:(NSMutableArray *)resetStyles isUpdateStyles:(BOOL)isUpdateStyles { - if ([self _isPropertyTransition]) { + if ([self _isPropertyTransitionStyles:styles]) { if (!_transition) { _transition = [WXTransition new]; } @@ -455,32 +454,40 @@ - (void)_updateStylesOnComponentThread:(NSDictionary *)styles resetStyles:(NSMut [self _resetCSSNodeStyles:resetStyles]; } -- (BOOL)_isPropertyTransition +- (BOOL)_isPropertyTransitionStyles:(NSDictionary *)styles { BOOL yesOrNo = false; - NSString *property = _styles[@"transitionProperty"]; + NSString *property = _styles[kWXTransitionProperty]; if (property) { - if ([property containsString:@"width"]||[property containsString:@"height"]||[property containsString:@"top"]||[property containsString:@"bottom"]||[property containsString:@"right"]||[property containsString:@"left"]||[property containsString:@"transform"]||[property containsString:@"backgroundColor"]||[property containsString:@"opacity"]) { + if (([property containsString:@"width"]&&styles[@"width"]) + ||([property containsString:@"height"]&&styles[@"height"]) + ||([property containsString:@"right"]&&styles[@"right"]) + ||([property containsString:@"left"]&&styles[@"left"]) + ||([property containsString:@"bottom"]&&styles[@"bottom"]) + ||([property containsString:@"top"]&&styles[@"top"]) + ||([property containsString:@"backgroundColor"]&&styles[@"backgroundColor"]) + ||([property containsString:@"transform"]&&styles[@"transform"]) + ||([property containsString:@"opacity"]&&styles[@"opacity"])) { yesOrNo = true; } } return yesOrNo; } - -- (BOOL)_isPropertyAnimation +- (BOOL)_isPropertyAnimationStyles:(NSDictionary *)styles { BOOL yesOrNo = false; - NSString *property = _styles[@"transitionProperty"]; + NSString *property = _styles[kWXTransitionProperty]; if (property) { - if ([property containsString:@"transform"]||[property containsString:@"backgroundColor"]||[property containsString:@"opacity"]) { + if (([property containsString:@"backgroundColor"]&&styles[@"backgroundColor"]) + ||([property containsString:@"transform"]&&styles[@"transform"]) + ||([property containsString:@"opacity"]&&styles[@"opacity"])) { yesOrNo = true; } } return yesOrNo; } - - (void)_modifyStyles:(NSDictionary *)styles { pthread_mutex_lock(&_propertyMutex); @@ -512,12 +519,11 @@ - (void)_removeEventOnComponentThread:(NSString *)eventName - (void)_updateStylesOnMainThread:(NSDictionary *)styles resetStyles:(NSMutableArray *)resetStyles { WXAssertMainThread(); - if (![self _isPropertyAnimation]) { + if (![self _isPropertyAnimationStyles:styles]) { [self _updateViewStyles:styles]; } [self _resetStyles:resetStyles]; [self _handleBorders:styles isUpdating:YES]; - [self updateStyles:styles]; [self resetStyles:resetStyles]; } diff --git a/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m b/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m index dc01af3a05..fa49d9e303 100644 --- a/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m +++ b/ios/sdk/WeexSDK/Sources/Module/WXAnimationModule.m @@ -313,9 +313,9 @@ - (void)animationWithLayoutAnimationTarget:(WXComponent *)target handleProperty: NSDictionary *styles = args[@"styles"]; _transition.addStyles = [NSMutableDictionary dictionaryWithDictionary:styles]; _transition.fromStyles =_transition.fromStyles ? :[NSMutableDictionary dictionaryWithDictionary:target.styles] ; - [_transition.fromStyles setObject:@([args[@"duration"] doubleValue]) forKey:@"transitionDuration"]; - [_transition.fromStyles setObject:@([args[@"delay"] doubleValue]) forKey:@"transitionDelay"]; - NSString *oldProperty = _transition.fromStyles[@"transitionProperty"]; + [_transition.fromStyles setObject:@([args[@"duration"] doubleValue]) forKey:kWXTransitionDuration]; + [_transition.fromStyles setObject:@([args[@"delay"] doubleValue]) forKey:kWXTransitionDelay]; + NSString *oldProperty = _transition.fromStyles[kWXTransitionProperty]; NSString *newProperty; if (oldProperty) { if ([oldProperty containsString:property]) { @@ -330,8 +330,8 @@ - (void)animationWithLayoutAnimationTarget:(WXComponent *)target handleProperty: { newProperty = property; } - [_transition.fromStyles setObject:newProperty forKey:@"transitionProperty"]; - [_transition.fromStyles setObject:args[@"timingFunction"] forKey:@"transitionTimingFunction"]; + [_transition.fromStyles setObject:newProperty forKey:kWXTransitionProperty]; + [_transition.fromStyles setObject:args[@"timingFunction"] forKey:kWXTransitionTimingFunction]; [target _modifyStyles:styles]; } diff --git a/ios/sdk/WeexSDK/Sources/Module/WXTransition.h b/ios/sdk/WeexSDK/Sources/Module/WXTransition.h index 9a0d5a8d6a..19870d2b90 100644 --- a/ios/sdk/WeexSDK/Sources/Module/WXTransition.h +++ b/ios/sdk/WeexSDK/Sources/Module/WXTransition.h @@ -19,6 +19,11 @@ #import +#define kWXTransitionDuration @"transitionDuration" +#define kWXTransitionProperty @"transitionProperty" +#define kWXTransitionDelay @"transitionDelay" +#define kWXTransitionTimingFunction @"transitionTimingFunction" + @interface WXLayoutAnimationInfo : NSObject @property (nonatomic, strong) id fromValue; @property (nonatomic, strong) id toValue; diff --git a/ios/sdk/WeexSDK/Sources/Module/WXTransition.m b/ios/sdk/WeexSDK/Sources/Module/WXTransition.m index 26d9fb9fc7..8758270337 100644 --- a/ios/sdk/WeexSDK/Sources/Module/WXTransition.m +++ b/ios/sdk/WeexSDK/Sources/Module/WXTransition.m @@ -75,15 +75,14 @@ - (void)_handleTransitionWithStyles:(NSDictionary *)styles withTarget:(WXCompone { [_addStyles addEntriesFromDictionary:styles]; } - _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"]]; + _layoutAnimationDuration = _fromStyles[kWXTransitionDuration] ? [WXConvert CGFloat:_fromStyles[kWXTransitionDuration]] : 0; + _layoutAnimationDelay = _fromStyles[kWXTransitionDelay] ? [WXConvert CGFloat:_fromStyles[kWXTransitionDelay]] : 0; + _layoutAnimationTimingFunction = [WXConvert CAMediaTimingFunction:_fromStyles[kWXTransitionTimingFunction]]; - if (_layoutAnimationDuration == 0) { + if (_layoutAnimationDuration == 0 ) { [targetComponent _updateCSSNodeStyles:styles]; WXPerformBlockOnMainThread(^{ [targetComponent _updateViewStyles:styles]; @@ -98,42 +97,54 @@ - (void)_handleTransitionWithStyles:(NSDictionary *)styles withTarget:(WXCompone [self unitBezierp1x:vec[0] p1y:vec[1] p2x:vec[2] p2y:vec[3]]; } - NSString *layoutAnimationProperty = _fromStyles[@"transitionProperty"]; + NSString *layoutAnimationProperty = _fromStyles[kWXTransitionProperty]; [self _resloveTransitionProperty:layoutAnimationProperty withStyles:styles]; [self performSelector:@selector(_startLayoutAnimationDisplayLink) withObject:self afterDelay:_layoutAnimationDelay/1000]; } - (void)_resloveTransitionProperty:(NSString *)propertyNames withStyles:(NSDictionary *)styles { - NSArray *array = @[@"width",@"height",@"top",@"bottom",@"right",@"left",@"transform",@"backgroundColor",@"opacity"]; + NSArray *array = @[@"width",@"height",@"top",@"bottom",@"right",@"left"]; for (NSString *propertyName in array) { if ([propertyNames containsString:propertyName]) { - [self _judgeProperty:propertyName withStyles:styles]; + [self _judgeProperty:propertyName ]; + } + } + NSArray *animationModuleArray = @[@"transform",@"backgroundColor",@"opacity"]; + for (NSString *propertyName in animationModuleArray) { + if ([propertyNames containsString:propertyName]) { + [self _dealWithAnimationModuleProperty:propertyName styles:styles]; } } } -- (void)_judgeProperty:(NSString *)singleProperty withStyles:(NSDictionary *)styles +- (void)_judgeProperty:(NSString *)singleProperty { - if (([singleProperty isEqualToString:@"transform"]&&styles[@"transform"]) || ([singleProperty containsString:@"backgroundColor"]&&styles[@"backgroundColor"]) || ([singleProperty containsString:@"opacity"]&&styles[@"opacity"])) { - NSDictionary *args = @{@"delay":@(_layoutAnimationDelay),@"duration":@(_layoutAnimationDuration),@"styles":styles,@"timingFunction":_fromStyles[@"transitionTimingFunction"]}; - [self _animationModuleHandleTransition:args]; + WXLayoutAnimationInfo *info = [WXLayoutAnimationInfo new]; + info.fromValue = @(_fromStyles[singleProperty] ? [WXConvert CGFloat:_fromStyles[singleProperty]] : 0); + info.toValue = @(_toStyles[singleProperty] ? [WXConvert CGFloat:_toStyles[singleProperty]] : 0 ); + info.perValue = @([info.toValue doubleValue] - [info.fromValue doubleValue]); + info.propertyName = singleProperty; + if (!_propertyArray) { + _propertyArray = [NSMutableArray new]; } - else{ - WXLayoutAnimationInfo *info = [WXLayoutAnimationInfo new]; - info.fromValue = @(_fromStyles[singleProperty] ? [WXConvert CGFloat:_fromStyles[singleProperty]] : 0); - info.toValue = @(_toStyles[singleProperty] ? [WXConvert CGFloat:_toStyles[singleProperty]] : 0 ); - info.perValue = @([info.toValue doubleValue] - [info.fromValue doubleValue]); - info.propertyName = singleProperty; - if (!_propertyArray) { - _propertyArray = [NSMutableArray new]; - } - [_propertyArray addObject:info]; + [_propertyArray addObject:info]; +} + +- (void)_dealWithAnimationModuleProperty:(NSString *)singleProperty styles:(NSDictionary *)styles +{ + if ([singleProperty isEqualToString:singleProperty]&&styles[singleProperty]) + { + NSDictionary *args = @{@"delay":@(_layoutAnimationDelay),@"duration":@(_layoutAnimationDuration),@"styles":styles,@"timingFunction":_fromStyles[kWXTransitionTimingFunction]}; + [self _animationModuleHandleTransition:args]; } } - (void)_calculateLayoutAnimationProcessingStyle { + if (_propertyArray.count == 0) { + return; + } 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)]; @@ -204,6 +215,7 @@ - (void)_resetProcessAnimationParameter { _layoutAnimationCount = 0; _layoutAnimationDuration = 0; + _propertyArray = nil; } From 75e4cf8707735caa37146fd62b5f17ca6c1f70f7 Mon Sep 17 00:00:00 2001 From: doumafang Date: Sat, 12 Aug 2017 12:27:36 +0800 Subject: [PATCH 5/6] * [ios] fix timingFunction bug --- ios/sdk/WeexSDK/Sources/Utility/WXConvert.m | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m index 72587906a9..18892e62b0 100644 --- a/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m +++ b/ios/sdk/WeexSDK/Sources/Utility/WXConvert.m @@ -672,7 +672,8 @@ + (CAMediaTimingFunction *)CAMediaTimingFunction:(id)value @"ease-in":kCAMediaTimingFunctionEaseIn, @"ease-out":kCAMediaTimingFunctionEaseOut, @"ease-in-out":kCAMediaTimingFunctionEaseInEaseOut, - @"linear":kCAMediaTimingFunctionLinear + @"linear":kCAMediaTimingFunctionLinear, + @"ease":kCAMediaTimingFunctionDefault }; }); From 7a4ee9339f2c27222677eb02bdf3629276af7147 Mon Sep 17 00:00:00 2001 From: doumafang Date: Mon, 14 Aug 2017 11:30:37 +0800 Subject: [PATCH 6/6] * [ios] fix build pbxproj bug --- ios/sdk/WeexSDK.xcodeproj/project.pbxproj | 24 +++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj index 1f39c41be3..db577c645f 100644 --- a/ios/sdk/WeexSDK.xcodeproj/project.pbxproj +++ b/ios/sdk/WeexSDK.xcodeproj/project.pbxproj @@ -37,8 +37,10 @@ 2AE5B7561CABA04E0082FDDB /* WXEventModuleProtocol.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AE5B7551CABA04E0082FDDB /* WXEventModuleProtocol.h */; settings = {ATTRIBUTES = (Public, ); }; }; 2AFEB17B1C747139000507FA /* WXInstanceWrap.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AFEB1791C747139000507FA /* WXInstanceWrap.h */; }; 2AFEB17C1C747139000507FA /* WXInstanceWrap.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AFEB17A1C747139000507FA /* WXInstanceWrap.m */; }; - 375A228F1EC440A600BC2086 /* WXAnimationLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 375A228D1EC440A600BC2086 /* WXAnimationLayout.m */; }; - 375A22901EC440A600BC2086 /* WXAnimationLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 375A228E1EC440A600BC2086 /* WXAnimationLayout.h */; }; + 333D9A271F41507A007CED39 /* WXTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 333D9A251F41507A007CED39 /* WXTransition.h */; }; + 333D9A281F41507A007CED39 /* WXTransition.h in Headers */ = {isa = PBXBuildFile; fileRef = 333D9A251F41507A007CED39 /* WXTransition.h */; }; + 333D9A291F41507A007CED39 /* WXTransition.m in Sources */ = {isa = PBXBuildFile; fileRef = 333D9A261F41507A007CED39 /* WXTransition.m */; }; + 333D9A2A1F41507A007CED39 /* WXTransition.m in Sources */ = {isa = PBXBuildFile; fileRef = 333D9A261F41507A007CED39 /* WXTransition.m */; }; 37B51EE41E97804D0040A743 /* WXCycleSliderComponent.h in Headers */ = {isa = PBXBuildFile; fileRef = 37B51EE21E97804D0040A743 /* WXCycleSliderComponent.h */; }; 37B51EE51E97804D0040A743 /* WXCycleSliderComponent.m in Sources */ = {isa = PBXBuildFile; fileRef = 37B51EE31E97804D0040A743 /* WXCycleSliderComponent.m */; }; 591324A31D49B7F1004E89ED /* WXTimerModuleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 591324A21D49B7F1004E89ED /* WXTimerModuleTests.m */; }; @@ -340,7 +342,6 @@ DCA445671EFA55B300D0CFA8 /* WXStorageModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 59A596211CB6311F0012CD52 /* WXStorageModule.m */; }; DCA445681EFA55B300D0CFA8 /* WXStreamModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 74A4BAA51CB4F98300195969 /* WXStreamModule.m */; }; DCA445691EFA55B300D0CFA8 /* WXAnimationModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 594C28901CF9E61A009793A4 /* WXAnimationModule.m */; }; - DCA4456A1EFA55B300D0CFA8 /* WXAnimationLayout.m in Sources */ = {isa = PBXBuildFile; fileRef = 375A228D1EC440A600BC2086 /* WXAnimationLayout.m */; }; DCA4456B1EFA55B300D0CFA8 /* WXInstanceWrap.m in Sources */ = {isa = PBXBuildFile; fileRef = 2AFEB17A1C747139000507FA /* WXInstanceWrap.m */; }; DCA4456C1EFA55B300D0CFA8 /* WXDomModule.m in Sources */ = {isa = PBXBuildFile; fileRef = 77E659D91C07F594008B8775 /* WXDomModule.m */; }; DCA4456D1EFA55B300D0CFA8 /* WXTimerModule.m in Sources */ = {isa = PBXBuildFile; fileRef = D3FC0DF61C508B2A002B9E31 /* WXTimerModule.m */; }; @@ -485,7 +486,6 @@ DCA445FB1EFA5A3C00D0CFA8 /* WXStorageModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 59A596201CB6311F0012CD52 /* WXStorageModule.h */; }; DCA445FC1EFA5A3E00D0CFA8 /* WXStreamModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 74A4BAA41CB4F98300195969 /* WXStreamModule.h */; }; DCA445FD1EFA5A4000D0CFA8 /* WXAnimationModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 594C28911CF9E61A009793A4 /* WXAnimationModule.h */; }; - DCA445FE1EFA5A4300D0CFA8 /* WXAnimationLayout.h in Headers */ = {isa = PBXBuildFile; fileRef = 375A228E1EC440A600BC2086 /* WXAnimationLayout.h */; }; DCA445FF1EFA5A4600D0CFA8 /* WXInstanceWrap.h in Headers */ = {isa = PBXBuildFile; fileRef = 2AFEB1791C747139000507FA /* WXInstanceWrap.h */; }; DCA446001EFA5A4800D0CFA8 /* WXDomModule.h in Headers */ = {isa = PBXBuildFile; fileRef = 77E659D81C07F594008B8775 /* WXDomModule.h */; }; DCA446011EFA5A4B00D0CFA8 /* WXTimerModule.h in Headers */ = {isa = PBXBuildFile; fileRef = D3FC0DF51C508B2A002B9E31 /* WXTimerModule.h */; }; @@ -597,8 +597,8 @@ 2AE5B7551CABA04E0082FDDB /* WXEventModuleProtocol.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXEventModuleProtocol.h; sourceTree = ""; }; 2AFEB1791C747139000507FA /* WXInstanceWrap.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXInstanceWrap.h; sourceTree = ""; }; 2AFEB17A1C747139000507FA /* WXInstanceWrap.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXInstanceWrap.m; sourceTree = ""; }; - 375A228D1EC440A600BC2086 /* WXAnimationLayout.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXAnimationLayout.m; sourceTree = ""; }; - 375A228E1EC440A600BC2086 /* WXAnimationLayout.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXAnimationLayout.h; sourceTree = ""; }; + 333D9A251F41507A007CED39 /* WXTransition.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXTransition.h; sourceTree = ""; }; + 333D9A261F41507A007CED39 /* WXTransition.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXTransition.m; sourceTree = ""; }; 37B51EE21E97804D0040A743 /* WXCycleSliderComponent.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WXCycleSliderComponent.h; sourceTree = ""; }; 37B51EE31E97804D0040A743 /* WXCycleSliderComponent.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXCycleSliderComponent.m; sourceTree = ""; }; 591324A21D49B7F1004E89ED /* WXTimerModuleTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WXTimerModuleTests.m; sourceTree = ""; }; @@ -1323,6 +1323,8 @@ 77E659D71C07F585008B8775 /* Module */ = { isa = PBXGroup; children = ( + 333D9A251F41507A007CED39 /* WXTransition.h */, + 333D9A261F41507A007CED39 /* WXTransition.m */, C43C03E41EC8ACA40044C7FF /* WXPrerenderManager.h */, C43C03E51EC8ACA40044C7FF /* WXPrerenderManager.m */, C4F012801E1502E9003378D0 /* WXWebSocketModule.h */, @@ -1341,8 +1343,6 @@ 74A4BAA51CB4F98300195969 /* WXStreamModule.m */, 594C28911CF9E61A009793A4 /* WXAnimationModule.h */, 594C28901CF9E61A009793A4 /* WXAnimationModule.m */, - 375A228D1EC440A600BC2086 /* WXAnimationLayout.m */, - 375A228E1EC440A600BC2086 /* WXAnimationLayout.h */, 2AFEB1791C747139000507FA /* WXInstanceWrap.h */, 2AFEB17A1C747139000507FA /* WXInstanceWrap.m */, 77E659D81C07F594008B8775 /* WXDomModule.h */, @@ -1506,7 +1506,6 @@ 74A4BA5B1CABBBD000195969 /* WXDebugTool.h in Headers */, 2A837AB41CD9DE9200AEDF03 /* WXLoadingIndicator.h in Headers */, 747A787C1D1BAAC900DED9D0 /* WXComponent+ViewManagement.h in Headers */, - 375A22901EC440A600BC2086 /* WXAnimationLayout.h in Headers */, 2AE5B7561CABA04E0082FDDB /* WXEventModuleProtocol.h in Headers */, C4C30DE91E1B833D00786B6C /* WXComponent+PseudoClassManagement.h in Headers */, 591DD3321D23AD5800BE8709 /* WXErrorView.h in Headers */, @@ -1566,6 +1565,7 @@ 742AD7331DF98C45007DC46C /* WXResourceResponse.h in Headers */, 77E65A0D1C155E99008B8775 /* WXDivComponent.h in Headers */, C41E1A971DC1FD15009C7F90 /* WXDatePickerManager.h in Headers */, + 333D9A271F41507A007CED39 /* WXTransition.h in Headers */, C4F0127B1E1502A6003378D0 /* WXWebSocketDefaultImpl.h in Headers */, 7461F8901CFB373100F62D44 /* WXDisplayQueue.h in Headers */, DCC77C141D770AE300CE7288 /* WXSliderNeighborComponent.h in Headers */, @@ -1632,6 +1632,7 @@ DCA445B91EFA579D00D0CFA8 /* WXErrorView.h in Headers */, DCA445A01EFA56F400D0CFA8 /* WXType.h in Headers */, DCA445B21EFA576D00D0CFA8 /* WXListComponent.h in Headers */, + 333D9A281F41507A007CED39 /* WXTransition.h in Headers */, DCA445A51EFA571600D0CFA8 /* WXSDKError.h in Headers */, DCA445AD1EFA575100D0CFA8 /* WXNavigationProtocol.h in Headers */, DCA445B01EFA576200D0CFA8 /* WXModalUIModule.h in Headers */, @@ -1680,7 +1681,6 @@ DCA445D01EFA593E00D0CFA8 /* WXDisplayQueue.h in Headers */, DCA445E91EFA59F900D0CFA8 /* WXSliderComponent.h in Headers */, DCA445E21EFA59D700D0CFA8 /* WXRefreshComponent.h in Headers */, - DCA445FE1EFA5A4300D0CFA8 /* WXAnimationLayout.h in Headers */, DCA445E81EFA59EF00D0CFA8 /* WXCycleSliderComponent.h in Headers */, DCA4461F1EFA5AB100D0CFA8 /* WXRuleManager.h in Headers */, DCA445E31EFA59DA00D0CFA8 /* WXEmbedComponent.h in Headers */, @@ -2023,7 +2023,6 @@ 59A5961D1CB630F10012CD52 /* WXComponent+Navigation.m in Sources */, 77D161631C02ED790010B15B /* WXLog.m in Sources */, 744BEA5A1D0520F300452B5D /* WXComponent+Layout.m in Sources */, - 375A228F1EC440A600BC2086 /* WXAnimationLayout.m in Sources */, 59A582FD1CF5B17B0081FD3E /* WXBridgeContext.m in Sources */, 743933B51C7ED9AA00773BB7 /* WXSimulatorShortcutManager.m in Sources */, 74BB5FBA1DFEE81A004FC3DF /* WXMetaModule.m in Sources */, @@ -2075,6 +2074,7 @@ 77E65A121C155EA8008B8775 /* WXImageComponent.m in Sources */, 2A837AB31CD9DE9200AEDF03 /* WXLoadingComponent.m in Sources */, 2AE5B7531CAB7DBD0082FDDB /* WXAComponent.m in Sources */, + 333D9A291F41507A007CED39 /* WXTransition.m in Sources */, 741DFE031DDD7D18009B020F /* WXRoundedRect.mm in Sources */, 59A596301CB632050012CD52 /* WXBaseViewController.m in Sources */, 74CC7A211C2BF9DC00829368 /* WXListComponent.m in Sources */, @@ -2174,7 +2174,6 @@ DCA445671EFA55B300D0CFA8 /* WXStorageModule.m in Sources */, DCA445681EFA55B300D0CFA8 /* WXStreamModule.m in Sources */, DCA445691EFA55B300D0CFA8 /* WXAnimationModule.m in Sources */, - DCA4456A1EFA55B300D0CFA8 /* WXAnimationLayout.m in Sources */, DCA4456B1EFA55B300D0CFA8 /* WXInstanceWrap.m in Sources */, DCA4456C1EFA55B300D0CFA8 /* WXDomModule.m in Sources */, DCA4456D1EFA55B300D0CFA8 /* WXTimerModule.m in Sources */, @@ -2207,6 +2206,7 @@ DCA445881EFA55B300D0CFA8 /* WXBridgeContext.m in Sources */, DCA445891EFA55B300D0CFA8 /* WXJSCoreBridge.m in Sources */, DCA4458A1EFA55B300D0CFA8 /* WXPolyfillSet.m in Sources */, + 333D9A2A1F41507A007CED39 /* WXTransition.m in Sources */, DCA4458B1EFA55B300D0CFA8 /* JSValue+Weex.m in Sources */, DCA4458C1EFA55B300D0CFA8 /* WXServiceFactory.m in Sources */, DCA4458D1EFA55B300D0CFA8 /* WXInvocationConfig.m in Sources */,