21

我有一个习惯UIView,可以在覆盖中绘制一些东西

- (void)drawRect:(CGRect)rect

这工作正常,并在视网膜屏幕上提供清晰的结果。

但是,现在我想使绘图所基于的属性可动画化。创建动画属性似乎只能在CALayer.UIViewCALayer

- (void) drawInContext:(CGContextRef)ctx

我在这个函数中使用了与我在drawRectcustom 函数中使用的几乎完全相同的绘图代码UIView

结果看起来一样 - 但是,它不是视网膜分辨率,而是像素化(大方形像素)

如果我把

self.contentsScale = [UIScreen mainScreen].scale;

在我的实现开始时drawInContext,我得到的不是像素化结果,而是模糊的结果(好像渲染仍然以非视网膜分辨率执行,然后放大到视网膜分辨率)。

渲染锐利视网膜路径的正确方法是CALayers drawInContext什么?

这是一些截图(蓝线是有问题的自定义绘图的一部分。黄色部分只是一个图像)

在自定义 UIView 中绘制drawRect

在此处输入图像描述

在自定义 CALayer 中绘制drawInContext

在此处输入图像描述

在自定义 CALayer 中绘制drawInContext,首先设置self.contentScale

在此处输入图像描述

为了完整起见,这里是(精简版的)绘图代码:

//if drawing inside custom UIView sublcass:
- (void)drawRect:(CGRect)rect
{
    CGContextRef currenctContext = UIGraphicsGetCurrentContext();
    [[UIColor blackColor] set];

    CGContextSetLineWidth(currenctContext, _lineWidth);
    CGContextSetLineJoin(currenctContext,kCGLineJoinRound);

    CGContextMoveToPoint(currenctContext,x1, y1);
    CGContextAddLineToPoint(currenctContext,x2, y2);
    CGContextStrokePath(currenctContext);
}

//if drawing inside custom CALayer subclass:
- (void) drawInContext:(CGContextRef)ctx {
{
    //self.contentsScale = [UIScreen mainScreen].scale;

    CGContextRef currenctContext = ctx;
    CGContextSetStrokeColorWithColor(currenctContext, [UIColor blackColor].CGColor);

    CGContextSetLineWidth(currenctContext, _lineWidth);
    CGContextSetLineJoin(currenctContext,kCGLineJoinRound);

    CGContextMoveToPoint(currenctContext,x1, y1);
    CGContextAddLineToPoint(currenctContext,x2, y2);
    CGContextStrokePath(currenctContext);
}

重申我想要实现的目标:我想要实现与UIView方法相同的清晰视网膜渲染,但是在渲染时CALayer

4

3 回答 3

17

问题很可能是 contentScale 这里;请注意,如果您通过覆盖其layerClass功能将其分配给自定义视图,则图层的内容比例可能会被重置。可能还有其他一些情况也会发生这种情况。为安全起见,请仅在将图层添加到视图后设置内容比例。

尝试在自定义视图的 init 方法中将主屏幕的比例分配给自定义层。在 Swift 3 中看起来像这样:

layer.contentsScale = UIScreen.mainScreen().scale

或者,在 Swift 4 中:

layer.contentsScale = UIScreen.main.scale
于 2016-08-21T20:48:01.190 回答
9

shouldRasterize = YES在图层中使用吗?尝试在 CALayer 子类中绘制,但将 设置rasterizationScale为屏幕的比例。

于 2015-02-06T13:43:07.173 回答
3

将图层添加到其超级图层后。将 shouldRasterize 设置为 YES ,将 contentsScale 和 resterizatioinScale 设置为屏幕比例:

[self.progressView.layer addSublayer:self.progressLayer];
self.progressLayer.shouldRasterize = YES;
self.progressLayer.contentsScale = kScreenScale;
self.progressLayer.rasterizationScale = kScreenScale;

CABasicAnimation *animate = [CABasicAnimation animationWithKeyPath:@"progress"];// progress is a customized property of progressLayer
animate.duration = 1.5;
animate.beginTime = 0;
animate.fromValue = @0;
animate.toValue = @1;
animate.fillMode = kCAFillModeForwards;
animate.removedOnCompletion = NO;
animate.repeatCount = HUGE_VALF;
[self.progressLayer addAnimation:animate forKey:@"progressAnimation"];
于 2016-10-13T06:46:15.757 回答