CALayer sublayerTransform 和 contentsScale 不能一起玩

Posted

技术标签:

【中文标题】CALayer sublayerTransform 和 contentsScale 不能一起玩【英文标题】:CALayer sublayerTransform and contentsScale do not play well together 【发布时间】:2011-07-02 10:20:01 【问题描述】:

我已经设置了一些这样的示例层。每层都将其子层内容缩小0.75

CGColorRef color = [UIColor colorWithRed:1 green:0 blue:0 alpha:1].CGColor;
CGRect frame = CGRectMake(0, 0, 128, 128);

m_layer0 = [CATextLayer new];
m_layer0.string = @"0";
m_layer0.frame = frame;
m_layer0.sublayerTransform = CATransform3DMakeScale(0.75, 0.75, 0.75);
m_layer0.masksToBounds = NO;
m_layer0.foregroundColor = color; 

m_layer1 = [CATextLayer new];
m_layer1.string = @"  1";
m_layer1.frame = frame;
m_layer1.sublayerTransform = CATransform3DMakeScale(0.75, 0.75, 0.75);
m_layer1.masksToBounds = NO;
m_layer1.foregroundColor = color;

m_layer2 = [CATextLayer new];
m_layer2.string = @"    2";
m_layer2.frame = frame;
m_layer2.sublayerTransform = CATransform3DMakeScale(0.75, 0.75, 0.75);
m_layer2.masksToBounds = NO;
m_layer2.foregroundColor = color;

[m_layer0 addSublayer:m_layer1];
[m_layer1 addSublayer:m_layer2];

[m_hostView.layer addSublayer:m_layer0];

hostViewUIScrollView 的子视图,在缩放时,我在其子层上设置了适当的contentsScale 因子以获得清晰的外观。

- (void)scrollViewDidEndZooming:(UIScrollView *)scrollView withView:(UIView *)view atScale:(float)scale 
    [CATransaction begin];
    [CATransaction setDisableActions:YES];
    m_layer0.contentsScale = scale;
    m_layer1.contentsScale = scale;
    m_layer2.contentsScale = scale;
    [CATransaction commit];

这会在放大时产生以下输出图像。

为什么第一个子层渲染正确,而那个子层却全是模糊的?

【问题讨论】:

我在 cocoa-dev 邮件列表中找到了hint。显然,比例变换不会按比例重新渲染内容。这似乎与显卡内存有关。 这似乎不是CATextLayer直接的问题,而是在CALayer-drawInContext:中绘制文本时也会发生。有什么建议吗? 当使用-drawInContext: 渲染时,您需要在每一层被滚动视图缩放后调用-setNeedsDisplay。不过我不确定CATextLayer 的行为。 不行,其实我一开始也是这样尝试的。 如果不了解您的代码,就很难判断出了什么问题。在这一点上,似乎只有在黑暗中刺伤才可能奏效。您是否确认您的滚动视图的委托已正确设置并且-scrollViewDidEndZooming... 实际上是通过签入调试器来调用的?抱歉,我无法提供更多帮助。 【参考方案1】:

我在这个上开了一个 TSI。这是解决方案:

问题是我正在缩放 Z 轴以及 X 和 Y 轴,这导致图层采用更复杂的渲染路径。所以CATransform3DMakeScale(0.75, 0.75, 1.0) 将是“正确”的做法。

如果您真的想在子层变换中启用 z 深度,您可以设置 m34 值,例如:

CATransform3D thisIsHowYouEnable3DForALayer = CATransform3DIdentity; 
thisIsHowYouEnable3DForALayer.m34 = -1.0/kSomeCameraDistanceValue;
parentView.layer.sublayerTransform = thisIsHowYouEnable3DForALayer;    

【讨论】:

以上是关于CALayer sublayerTransform 和 contentsScale 不能一起玩的主要内容,如果未能解决你的问题,请参考以下文章

如何将 CALayer 子类化为另一个 CALayer 掩码?

移动CALayer位置完全被超级CALayer封装

如何检测两个 CALayer 是不是重叠?

UIView与CALayer的区别

Calayer子类问题

iOS 中 UIView 和 CALayer 的关系