@@ -79,8 +79,8 @@ class AnimationDelegateImpl extends NSObject implements CAAnimationDelegate {
79
79
targetStyle [ setLocal ? widthProperty . name : widthProperty . keyframe ] = value ;
80
80
break ;
81
81
case Properties . scale :
82
- targetStyle [ setLocal ? scaleXProperty . name : scaleXProperty . keyframe ] = value . x === 0 ? 1e-6 : value . x ;
83
- targetStyle [ setLocal ? scaleYProperty . name : scaleYProperty . keyframe ] = value . y === 0 ? 1e-6 : value . y ;
82
+ targetStyle [ setLocal ? scaleXProperty . name : scaleXProperty . keyframe ] = value . x === 0 ? 0.001 : value . x ;
83
+ targetStyle [ setLocal ? scaleYProperty . name : scaleYProperty . keyframe ] = value . y === 0 ? 0.001 : value . y ;
84
84
break ;
85
85
case _transform :
86
86
if ( value [ Properties . translate ] !== undefined ) {
@@ -95,8 +95,8 @@ class AnimationDelegateImpl extends NSObject implements CAAnimationDelegate {
95
95
if ( value [ Properties . scale ] !== undefined ) {
96
96
const x = value [ Properties . scale ] . x ;
97
97
const y = value [ Properties . scale ] . y ;
98
- targetStyle [ setLocal ? scaleXProperty . name : scaleXProperty . keyframe ] = x === 0 ? 1e-6 : x ;
99
- targetStyle [ setLocal ? scaleYProperty . name : scaleYProperty . keyframe ] = y === 0 ? 1e-6 : y ;
98
+ targetStyle [ setLocal ? scaleXProperty . name : scaleXProperty . keyframe ] = x === 0 ? 0.001 : x ;
99
+ targetStyle [ setLocal ? scaleYProperty . name : scaleYProperty . keyframe ] = y === 0 ? 0.001 : y ;
100
100
}
101
101
break ;
102
102
}
@@ -309,6 +309,7 @@ export class Animation extends AnimationBase {
309
309
const parent = view . parent as View ;
310
310
311
311
let propertyNameToAnimate = animation . property ;
312
+ let subPropertyNameToAnimate ;
312
313
let toValue = animation . value ;
313
314
let fromValue ;
314
315
if ( nativeView ) {
@@ -334,6 +335,8 @@ export class Animation extends AnimationBase {
334
335
} ;
335
336
fromValue = nativeView . layer . opacity ;
336
337
break ;
338
+ // In the case of rotation, avoid animating affine transform directly as it will animate to the closest result
339
+ // that is visually the same. For example, 0 -> 360 will leave view as is.
337
340
case Properties . rotate :
338
341
animation . _originalValue = {
339
342
x : view . rotateX ,
@@ -346,9 +349,30 @@ export class Animation extends AnimationBase {
346
349
style [ setLocal ? rotateYProperty . name : rotateYProperty . keyframe ] = value . y ;
347
350
} ;
348
351
349
- propertyNameToAnimate = 'transform' ;
350
- fromValue = NSValue . valueWithCATransform3D ( nativeView . layer . transform ) ;
351
- toValue = NSValue . valueWithCATransform3D ( iosHelper . applyRotateTransform ( nativeView . layer . transform , toValue . x , toValue . y , toValue . z ) ) ;
352
+ propertyNameToAnimate = 'transform.rotation' ;
353
+ subPropertyNameToAnimate = [ 'x' , 'y' , 'z' ] ;
354
+ fromValue = {
355
+ x : nativeView . layer . valueForKeyPath ( 'transform.rotation.x' ) ,
356
+ y : nativeView . layer . valueForKeyPath ( 'transform.rotation.y' ) ,
357
+ z : nativeView . layer . valueForKeyPath ( 'transform.rotation.z' ) ,
358
+ } ;
359
+
360
+ if ( animation . target . rotateX !== undefined && animation . target . rotateX !== 0 && Math . floor ( toValue / 360 ) - toValue / 360 === 0 ) {
361
+ fromValue . x = ( animation . target . rotateX * Math . PI ) / 180 ;
362
+ }
363
+ if ( animation . target . rotateY !== undefined && animation . target . rotateY !== 0 && Math . floor ( toValue / 360 ) - toValue / 360 === 0 ) {
364
+ fromValue . y = ( animation . target . rotateY * Math . PI ) / 180 ;
365
+ }
366
+ if ( animation . target . rotate !== undefined && animation . target . rotate !== 0 && Math . floor ( toValue / 360 ) - toValue / 360 === 0 ) {
367
+ fromValue . z = ( animation . target . rotate * Math . PI ) / 180 ;
368
+ }
369
+
370
+ // Respect only value.z for back-compat until 3D rotations are implemented
371
+ toValue = {
372
+ x : ( toValue . x * Math . PI ) / 180 ,
373
+ y : ( toValue . y * Math . PI ) / 180 ,
374
+ z : ( toValue . z * Math . PI ) / 180 ,
375
+ } ;
352
376
break ;
353
377
case Properties . translate :
354
378
animation . _originalValue = {
@@ -365,10 +389,10 @@ export class Animation extends AnimationBase {
365
389
break ;
366
390
case Properties . scale :
367
391
if ( toValue . x === 0 ) {
368
- toValue . x = 1e-6 ;
392
+ toValue . x = 0.001 ;
369
393
}
370
394
if ( toValue . y === 0 ) {
371
- toValue . y = 1e-6 ;
395
+ toValue . y = 0.001 ;
372
396
}
373
397
animation . _originalValue = { x : view . scaleX , y : view . scaleY } ;
374
398
animation . _propertyResetCallback = ( value , valueSource ) => {
@@ -451,6 +475,7 @@ export class Animation extends AnimationBase {
451
475
return {
452
476
propertyNameToAnimate : propertyNameToAnimate ,
453
477
fromValue : fromValue ,
478
+ subPropertiesToAnimate : subPropertyNameToAnimate ,
454
479
toValue : toValue ,
455
480
duration : duration ,
456
481
repeatCount : repeatCount ,
@@ -496,10 +521,10 @@ export class Animation extends AnimationBase {
496
521
}
497
522
498
523
private static _createGroupAnimation ( args : AnimationInfo , animation : PropertyAnimation ) {
499
- const animations = NSMutableArray . alloc < CAAnimation > ( ) . initWithCapacity ( args . subPropertiesToAnimate . length ) ;
500
524
const groupAnimation = CAAnimationGroup . new ( ) ;
501
- groupAnimation . duration = args . duration ;
525
+ const animations = NSMutableArray . alloc < CAAnimation > ( ) . initWithCapacity ( args . subPropertiesToAnimate . length ) ;
502
526
527
+ groupAnimation . duration = args . duration ;
503
528
if ( args . repeatCount !== undefined ) {
504
529
groupAnimation . repeatCount = args . repeatCount ;
505
530
}
@@ -651,30 +676,16 @@ export class Animation extends AnimationBase {
651
676
}
652
677
653
678
if ( value [ Properties . scale ] !== undefined ) {
654
- const x = value [ Properties . scale ] . x || 1e-6 ;
655
- const y = value [ Properties . scale ] . y || 1e-6 ;
656
- result = CATransform3DScale ( result , x , y , 1 ) ;
657
- }
658
-
659
- if ( value [ Properties . rotate ] !== undefined ) {
660
- const x = value [ Properties . rotate ] . x ;
661
- const y = value [ Properties . rotate ] . y ;
662
- const z = value [ Properties . rotate ] . z ;
663
- const perspective = animation . target . perspective || 300 ;
664
-
665
- // Set perspective in case of rotation since we use z
666
- if ( x || y ) {
667
- result . m34 = - 1 / perspective ;
668
- }
669
-
670
- result = iosHelper . applyRotateTransform ( result , x , y , z ) ;
679
+ const x = value [ Properties . scale ] . x ;
680
+ const y = value [ Properties . scale ] . y ;
681
+ result = CATransform3DScale ( result , x === 0 ? 0.001 : x , y === 0 ? 0.001 : y , 1 ) ;
671
682
}
672
683
673
684
return result ;
674
685
}
675
686
676
687
private static _isAffineTransform ( property : string ) : boolean {
677
- return property === _transform || property === Properties . translate || property === Properties . scale || property === Properties . rotate ;
688
+ return property === _transform || property === Properties . translate || property === Properties . scale ;
678
689
}
679
690
680
691
private static _canBeMerged ( animation1 : PropertyAnimation , animation2 : PropertyAnimation ) {
@@ -941,8 +952,7 @@ function calculateTransform(view: View): CATransform3D {
941
952
// Order is important: translate, rotate, scale
942
953
let expectedTransform = new CATransform3D ( CATransform3DIdentity ) ;
943
954
944
- // TODO: Add perspective property to transform animations (not just rotation)
945
- // Set perspective in case of rotation since we use z
955
+ // Only set perspective if there is 3D rotation
946
956
if ( view . rotateX || view . rotateY ) {
947
957
expectedTransform . m34 = - 1 / perspective ;
948
958
}
0 commit comments