我以前从未遇到过这种情况,无法弄清楚发生了什么。我怀疑它可能是自动布局,但我不知道如何。我有一个“指南针” View ,它有几个它自己管理的 subview (不是自动布局的一部分)。这是他们的设置示例:
- (ITMView *) compass {
if (!_compass){
_compass = [ITMView new];
_compass.backgroundColor = [UIColor blueColor];
_compass.layer.anchorPoint = CGPointMake(.5, .5);
_compass.translatesAutoresizingMaskIntoConstraints = NO;
_compass.frame = self.bounds;
__weak ITMCompassView *_self = self;
_compass.onDraw = ^(CGContextRef ref, CGRect frame) { [_self drawCompassWithFrame:frame]; };
[self addSubview:_compass];
}
return _compass;
}
我需要旋转指南针以响应航向变化:
- (void) setCurrentHeading:(double)currentHeading{
_currentHeading = fmod(currentHeading, 360);
double rad = (M_PI / 180) * _currentHeading;
self.compass.transform = CGAffineTransformMakeRotation(rad);
}
问题是由于某种原因它在 z 轴上旋转:
我不会在任何其他 View 上操作图层变换。有谁知道为什么会这样?
更新
我检查了所有 super View 的转换。每个父 View 都有一个身份转换。
我记录了第一次设置罗盘 View 前后的变化。在它被设置之前,转换是在 identity,这是预期的。在我将变换设置为旋转 242.81
度(4.24
弧度)后,我得到:
[
-0.47700124155378526, -0.87890262006444575,
0.87890262006444575, -0.47700124155378526,
0, 0
]
更新2
我检查了 CATransform3DIsAffine
,它总是返回 YES
。我仔细检查了层变换并旋转了 159.7
(度),我得到:
[
-0.935, 0.356, 0, 0,
-0.356, -0.935, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
]
这对我来说是正确的。
所有的转换都是正确的,但它仍然没有在屏幕上正确显示。
更新3
我从 View 中删除了绘图代码并将 View 背景设置为蓝色。 View 肯定在旋转、挤压或其他情况:
一些注意事项:
- View 可正确显示 90、180、270 和 0 度。
- View 在 45、135、225 和 315 度时消失(在边缘打开)。
- View 看起来在从 0 度到 360 度的过程中以 3D 方式旋转。
最佳答案
我不确定为什么 @matt 撤回了他的回答,但他是正确的:每次我在包含 super View 的 layoutSubviews
方法中进行旋转时,罗盘 View 都会重置其框架。我没想到会这样,认为旋转不会触发 layoutSubviews
。框架从未改变,但应用的变换扭曲了结果,因为框架被重新应用到 View 。令我震惊的是,结果确实看起来 View 在 3D 中旋转,这让我陷入了那个特别的兔子洞。至少我知道现在要寻找什么。
有一点我想指出:明显的 3D 旋转非常特别。它在单位圆的每个 90° 象限之间依次围绕 {x,Y} 的每个对角线组合旋转。如果您考虑框架在这些时期内会如何扭曲,这是有道理的。
解决方案很简单,在设置 subview 框架之前存储和删除变换,然后重新应用变换。然而,因为旋转应用得非常非常频繁(在动画 block 内)我添加了一个转义符来帮助减少负载:
- (void) layoutSubviews{
[super layoutSubviews];
if (!CGRectEqualToRect(_lastLayout, self.bounds)){
CGRect frame = SquareRectAndPosition(self.bounds, CGRectXCenter, CGRectYCenter);
CGAffineTransform t;
t = self.compass.transform;
self.compass.transform = CGAffineTransformIdentity;
self.compass.frame = frame;
self.compass.transform = t;
t = self.target.transform;
self.target.transform = CGAffineTransformIdentity;
self.target.frame = frame;
self.target.transform = t;
}
_lastLayout = self.bounds;
}
关于ios - CGAffineTransformMakeRotation 在 3D 中旋转,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28385371/