我以前从来没有这样做过,也无法弄清楚发生了什么。我怀疑它可能是自动布局,但我不知道如何。我有一个" Compass"视图,它有自己管理的几个子视图(不是自动布局的一部分)。以下是他们设置的示例:
- (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轴上旋转:
我没有在任何其他视图上操纵图层变换。有谁知道为什么会这样?
我检查了所有超级视图的转换。每个超级视图都有一个身份变换。
我在第一次设置之前和之后记录了罗盘视图的变换。在它被设定之前,转变是在身份,这是预期的。在我将变换设置为旋转242.81
度(4.24
rad)后,我得到:
[
-0.47700124155378526, -0.87890262006444575,
0.87890262006444575, -0.47700124155378526,
0, 0
]
我检查了CATransform3DIsAffine
,它总是返回YES
。我仔细检查了图层变换,并且我得到了159.7
(度)的旋转:
[
-0.935, 0.356, 0, 0,
-0.356, -0.935, 0, 0,
0, 0, 1, 0,
0, 0, 0, 1
]
这对我来说是正确的。
所有变换都是正确的,但仍无法在屏幕上正确显示。
我从视图中删除了我的绘图代码,并将视图背景设置为蓝色。视图肯定是旋转,挤压或其他东西:
有些注意事项:
答案 0 :(得分:1)
我不确定为什么@matt撤回了他的答案,但他是正确的:每次我在我的包含超视图中的layoutSubviews
方法中进行旋转时,罗盘视图都会重置帧。我没想到这一点,认为轮换不会触发layoutSubviews
。帧永远不会改变,但是当帧重新应用于视图时,应用的变换会使结果失真。让我印象深刻的是结果真的看起来就像视图在3D中旋转一样,这让我陷入了那个特殊的兔子洞。至少我知道现在要找什么。
我想指出的一点:明显的3D旋转非常特别。它在单位圆的每个90°象限之间顺序地围绕{x,Y}的每个对角线组合旋转。如果您考虑帧在这些时段内如何扭曲,这是有道理的。
解决方案很简单,在设置子视图帧之前存储和删除变换,然后重新应用变换。但是,因为非常频繁地应用旋转(在动画块内部也不少),我添加了一个转义来帮助减少负载:
- (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;
}