Skip to content

Commit bf133b9

Browse files
Nick LefeverSaadnajmi
authored andcommitted
[fabric] Adapt transforms to CALayer top-left anchor point
Summary: On macOS, Core Animation layers have their anchor point set to (0,0) which is the top-left. On iOS the anchor point is set to (0.5, 0.5) which matches the center. Transforms assigned to views are built based on having the anchor point at the center. This diff updates the transform matrix to apply to transform from the center. Test Plan: Check zoom/rotation animations in Zeratul. | Before | After | |--| | https://pxl.cl/3G8HG | https://pxl.cl/3G8HQ | Reviewers: shawndempsey, #rn-desktop Reviewed By: shawndempsey Differential Revision: https://phabricator.intern.facebook.com/D50628807 Tasks: T161413049
1 parent ba3269f commit bf133b9

File tree

2 files changed

+15
-0
lines changed

2 files changed

+15
-0
lines changed

packages/react-native/React/Fabric/Mounting/ComponentViews/View/RCTViewComponentView.mm

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -332,6 +332,15 @@ - (void)updateProps:(const Props::Shared &)props oldProps:(const Props::Shared &
332332
![_propKeysManagedByAnimated_DO_NOT_USE_THIS_IS_BROKEN containsObject:@"transform"]) {
333333
auto newTransform = newViewProps.resolveTransform(_layoutMetrics);
334334
CATransform3D caTransform = RCTCATransform3DFromTransformMatrix(newTransform);
335+
#if TARGET_OS_OSX // [macOS
336+
CGPoint anchorPoint = self.layer.anchorPoint;
337+
if (CGPointEqualToPoint(anchorPoint, CGPointZero) && !CATransform3DEqualToTransform(caTransform, CATransform3DIdentity)) {
338+
// https://developer.apple.com/documentation/quartzcore/calayer/1410817-anchorpoint
339+
// This compensates for the fact that layer.anchorPoint is {0, 0} instead of {0.5, 0.5} on macOS for some reason.
340+
CATransform3D originAdjust = CATransform3DTranslate(CATransform3DIdentity, self.frame.size.width / 2, self.frame.size.height / 2, 0);
341+
caTransform = CATransform3DConcat(CATransform3DConcat(CATransform3DInvert(originAdjust), caTransform), originAdjust);
342+
}
343+
#endif // macOS]
335344

336345
self.layer.transform = caTransform;
337346
// Enable edge antialiasing in rotation, skew, or perspective transforms

packages/react-native/React/Fabric/Mounting/RCTMountingManager.mm

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -309,6 +309,12 @@ - (void)synchronouslyUpdateViewOnUIThread:(ReactTag)reactTag
309309
layoutMetrics.frame.size.width = componentView.layer.bounds.size.width;
310310
layoutMetrics.frame.size.height = componentView.layer.bounds.size.height;
311311
CATransform3D newTransform = RCTCATransform3DFromTransformMatrix(newViewProps.resolveTransform(layoutMetrics));
312+
#if TARGET_OS_OSX // [macOS]
313+
if (CGPointEqualToPoint(componentView.layer.anchorPoint, CGPointZero) && !CATransform3DEqualToTransform(newTransform, CATransform3DIdentity)) {
314+
CATransform3D originAdjust = CATransform3DTranslate(CATransform3DIdentity, componentView.frame.size.width / 2, componentView.frame.size.height / 2, 0);
315+
newTransform = CATransform3DConcat(CATransform3DConcat(CATransform3DInvert(originAdjust), newTransform), originAdjust);
316+
}
317+
#endif // macOS]
312318
if (!CATransform3DEqualToTransform(newTransform, componentView.layer.transform)) {
313319
componentView.layer.transform = newTransform;
314320
}

0 commit comments

Comments
 (0)