【问题标题】:CAShapeLayer as a mask for CALayer: rounded corners are stretchedCAShapeLayer 作为 CALayer 的遮罩:圆角被拉伸
【发布时间】:2011-10-21 19:15:52
【问题描述】:

我想用CAShapeLayer 屏蔽CALayer,因为可以对形状的更改进行动画处理。

当我使用CAShapeLayer 作为蒙版时,圆角被拉伸。但是,如果我采用相同的形状,用它创建一个NSImage,并使用图像来掩盖我的CALayer,圆角就很好了。

这是我用来屏蔽图层的代码(您也可以下载整个example project):

CGColorRef backgroundColor = CGColorCreateGenericRGB(0.0, 0.0, 0.0, 1.0f);

[self.window.contentView setLayer:[CALayer layer]];
[self.window.contentView setWantsLayer:YES];
[[self.window.contentView layer] setFrame:[self.window.contentView frame]];


CALayer *imageBasedMaskLayer = [CALayer layer];
[imageBasedMaskLayer setContents:(id)[[self maskWithSize:NSMakeSize(50, 50)] CGImageForProposedRect:NULL context:nil hints:nil]];
[imageBasedMaskLayer setFrame:CGRectMake(0, 0, 50, 50)];

CALayer *layerWithImageBasedMaskLayer = [CALayer layer];
[layerWithImageBasedMaskLayer setBackgroundColor:backgroundColor];
[layerWithImageBasedMaskLayer setMask:imageBasedMaskLayer];


CAShapeLayer *shapeBasedMaskLayer = [CAShapeLayer layer];
CGPathRef maskShape = [self newMaskPathWithFrame:NSMakeRect(0, 0, 50, 50)];
[shapeBasedMaskLayer setPath:maskShape];
[shapeBasedMaskLayer setFillRule:kCAFillRuleEvenOdd];
CGPathRelease(maskShape);
[shapeBasedMaskLayer setFrame:CGRectMake(0, 0, 50, 50)];

CALayer *layerWithShapeBasedMaskLayer = [CALayer layer];
[layerWithShapeBasedMaskLayer setBackgroundColor:backgroundColor];
[layerWithShapeBasedMaskLayer setMask:nil];
[layerWithShapeBasedMaskLayer setMask:shapeBasedMaskLayer];


[layerWithImageBasedMaskLayer setFrame:CGRectMake(50, 50, 50, 50)];
[layerWithShapeBasedMaskLayer setFrame:CGRectMake(120, 50, 50, 50)];
[[self.window.contentView layer] addSublayer:layerWithImageBasedMaskLayer];
[[self.window.contentView layer] addSublayer:layerWithShapeBasedMaskLayer];

CGColorRelease(backgroundColor);

还有我用来创建NSImageCGPathRef 的两种方法。

- (NSImage *)maskWithSize:(CGSize)size;
{
    NSImage *maskImage = [[NSImage alloc] initWithSize:size];

    [maskImage lockFocus];
    [[NSColor blackColor] setFill];

    CGPathRef mask = [self newMaskPathWithFrame:CGRectMake(0, 0, size.width, size.height)];
    CGContextRef context = [[NSGraphicsContext currentContext] graphicsPort];
    CGContextAddPath(context, mask);
    CGContextFillPath(context);
    CGPathRelease(mask);

    [maskImage unlockFocus];

    return [maskImage autorelease];
}

- (CGPathRef)newMaskPathWithFrame:(CGRect)frame; 
{
    CGFloat cornerRadius = 3;

    CGFloat height = CGRectGetMaxY(frame);
    CGFloat width = CGRectGetMaxX(frame);

    CGMutablePathRef maskPath = CGPathCreateMutable();

    CGPathMoveToPoint(maskPath, NULL, 0, height-cornerRadius);
    CGPathAddArcToPoint(maskPath, NULL, 0, height, cornerRadius, height, cornerRadius);
    CGPathAddLineToPoint(maskPath, NULL, width-cornerRadius, height);
    CGPathAddArcToPoint(maskPath, NULL, width, height, width, height-cornerRadius, cornerRadius);
    CGPathAddLineToPoint(maskPath, NULL, width, cornerRadius);
    CGPathAddArcToPoint(maskPath, NULL, width, 0, width-cornerRadius, 0, cornerRadius);
    CGPathAddLineToPoint(maskPath, NULL, cornerRadius, 0);
    CGPathAddArcToPoint(maskPath, NULL, 0, 0, 0, cornerRadius, cornerRadius);

    CGPathCloseSubpath(maskPath);

    return maskPath;
}

请注意,我要创建的实际蒙版比圆角矩形更复杂,否则我会使用一些更简单的绘图技术。我尝试了各种CGPath的绘图功能,问题并没有消失。

我在这里错过了什么?

【问题讨论】:

  • 这很奇怪。这听起来像一个系统错误。我建议使用 Apple 的错误报告器记录错误。
  • 这确实很奇怪。另一个可能有趣的数据点:如果您将cornerRadius 设置为3,而不是使用形状图层进行遮罩,那么它看起来是正确的。 (即没有表现出拉伸)我知道这并不能解决你的问题,但它增加了神秘感。

标签: objective-c core-animation core-graphics


【解决方案1】:

那是因为CAShapeLayer 更注重速度而不是准确性。这就是为什么它有时可能会关闭。

图形将被抗锯齿绘制,并尽可能在光栅化之前将其映射到屏幕空间以保持分辨率独立性。但是,应用于图层或其祖先的某些类型的图像处理操作(例如 CoreImage 过滤器)可能会强制在局部坐标空间中进行光栅化。

注意:形状光栅化可能有利于速度而不是准确性。例如,具有多个相交路径段的像素可能无法给出准确的结果。

http://developer.apple.com/library/Mac/#documentation/GraphicsImaging/Reference/CAShapeLayer_class/Reference/Reference.html

解决方案

你可以使用

layerWithShapeBasedMaskLayer.cornerRadius = 3.0;

圆你所有的角落。您不再需要CAShapeLayer。您甚至可以继续使用您的CAShapeLayer 作为子图层来为路径设置动画。设置好了

layerWithShapeBasedMaskLayer.masksToBounds = YES;

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-02-24
    • 1970-01-01
    • 2014-11-17
    • 2016-03-16
    • 1970-01-01
    相关资源
    最近更新 更多