我将CALayer的.contents设置为CGImage,从绘制到NSBitMapImageRep中派生出来。
据我所知,从文档和WWDC视频中,将图层的.contentsCenter设置为类似{{0.5,0.5},{0,0}}的NSRect,并结合kCAGravityResize的.contentsGravity应该导致Core动画通过拉伸中间像素,水平顶部和底部以及垂直侧面来调整图层大小。
这几乎可行,但并不完全。图层或多或少地正确调整大小,但如果我在位图的边缘绘制线条,当我调整窗口大小时,可以看到线条的厚度非常轻微地波动。在调整大小降低到原始图层大小的1/4左右之前,它的微妙程度几乎不会成为问题,低于这一点,线条可以变薄并完全消失。如果我以不同的尺寸多次绘制位图,则线条厚度的微小差异非常明显。
我最初研究了一个像素对齐问题,但不能这样,因为当我调整RH边缘的大小时,静止LH边缘(例如)的厚度会波动。它发生在1x和2x屏幕上。
这是一些测试代码。它是来自图层支持的NSView子类的updateLayer方法(我正在使用替代的非DrawRect绘制路径):
- (void)updateLayer {
id image = [self imageForCurrentScaleFactor]; // CGImage
self.layer.contents = image;
// self.backingScaleFactor is set from the window's backingScaleFactor
self.layer.contentsScale = self.backingScaleFactor;
self.layer.contentsCenter = NSMakeRect(0.5, 0.5, 0, 0);
self.layer.contentsGravity = kCAGravityResize;
}
这里有一些测试绘图代码(创建上面的imageForCurrentScaleFactor提供的图像):
CGFloat width = rect.size.width;
CGFloat height = rect.size.height;
NSBitmapImageRep *imageRep = [[NSBitmapImageRep alloc] initWithBitmapDataPlanes: NULL
pixelsWide: width * scaleFactor
pixelsHigh: height * scaleFactor
bitsPerSample: 8
samplesPerPixel: 4
hasAlpha: YES
isPlanar: NO
colorSpaceName: NSCalibratedRGBColorSpace
bytesPerRow: 0
bitsPerPixel: 0];
[imageRep setSize:rect.size];
[NSGraphicsContext saveGraphicsState];
NSGraphicsContext *ctx = [NSGraphicsContext graphicsContextWithBitmapImageRep:imageRep];
[NSGraphicsContext setCurrentContext:ctx];
[[NSColor whiteColor] setFill];
[NSBezierPath fillRect:rect];
[[NSColor blackColor] setStroke];
[NSBezierPath setDefaultLineWidth:1.0f];
[NSBezierPath strokeRect:insetRect];
[NSGraphicsContext restoreGraphicsState];
// image for CALayer.contents is now [imageRep CGImage]
答案 0 :(得分:0)
解决方案(如果您正在谈论我认为您正在讨论的问题)是在图像的外边缘处形成透明像素边距。一个像素厚,一直到处都可以。原因是问题(如果它是我认为的问题)仅出现在触摸图像外边缘的可见像素上。因此,我们的想法是让没有可见像素触及图像的外边缘。
答案 1 :(得分:0)
我找到了一个实际的答案,但是会对那些知道如何运作的人详细填写评论感兴趣。
问题确实与CALayer的拉伸方式有关。我正在绘制一个任意大小的位图,基于(如CALayer文档建议的那样)使用零宽度和高度的.contentsCenter实际上会进行九部分图像拉伸,选择单个中心像素作为中央拉伸部分。将此位图作为图层的.contents,然后我可以将CALayer的大小调整为任何所需的大小(向下或向上)。
原来,'画布尺寸'是问题。 CALayer拉伸边缘部分的方式发生了奇怪的事情(至少在调整大小时)。相反,通过使绘制的初始框架变得很小(即,足够大以适合我的轮廓绘图加上中心拉伸部分的几个像素),在拉伸过程中没有任何虚假的东西进入边缘。
如果使用rect创建的位图刚好足以适合内容和可伸展的中心像素,则位图会正确拉伸,即:
NSRect rect = NSMakeRect(0, 0, lineWidth * 2 + 2, lineWidth * 2 + 2);
这个微小的图像完美地延伸到任何更大的尺寸。