gpt4 book ai didi

objective-c - CAShapeLayer 作为 CALayer 的掩码 : rounded corners are stretched

转载 作者:太空狗 更新时间:2023-10-30 03:38:24 27 4
gpt4 key购买 nike

我想用 CAShapeLayer 遮盖 CALayer,因为可以对形状的变化进行动画处理。

当我使用 CAShapeLayer 作为 mask 时,圆角被拉伸(stretch)了。但是,如果我采用相同的形状,用它创建一个 NSImage,并使用该图像遮盖我的 CALayer,圆角就非常好。

Rounded corners with NSImage on the left, CAShapeLayer on the right

这是我用来屏蔽图层的代码(您也可以下载整个 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;
}

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

我在这里错过了什么?

最佳答案

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

The shape will be drawn antialiased, and whenever possible it will be mapped into screen space before being rasterized to preserve resolution independence. However, certain kinds of image processing operations, such as CoreImage filters, applied to the layer or its ancestors may force rasterization in a local coordinate space.

Note: Shape rasterization may favor speed over accuracy. For example, pixels with multiple intersecting path segments may not give exact results.

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

解决方案

你可以使用

layerWithShapeBasedMaskLayer.cornerRadius = 3.0;

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

layerWithShapeBasedMaskLayer.masksToBounds = YES;

关于objective-c - CAShapeLayer 作为 CALayer 的掩码 : rounded corners are stretched,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/7854220/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com