Ответ 1
Используете ли вы shouldRasterize = YES
в слое? Попробуйте выполнить рисование в подклассе CALayer, но установите rasterizationScale
на экранную шкалу.
У меня есть пользовательский UIView
который рисует что-то в перезаписанном
- (void)drawRect:(CGRect)rect
это прекрасно работает и дает четкие результаты на экранах сетчатки.
Однако теперь я хотел бы сделать свойства, на которых основан чертеж, анимируемыми. Создание анимируемых свойств представляется возможным только в CALayer
, поэтому вместо рисования в UIView
я создаю собственный подкласс CALayer
и выполняю рисование внутри
- (void) drawInContext:(CGContextRef)ctx
В этой функции я использую практически тот же код рисования, что и в функции drawRect
пользовательского 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
Используете ли вы shouldRasterize = YES
в слое? Попробуйте выполнить рисование в подклассе CALayer, но установите rasterizationScale
на экранную шкалу.
Проблема, скорее всего, будет contentScale здесь; имейте в виду, что если вы назначаете это настраиваемому представлению, переопределяя его функцию layerClass
, масштаб содержимого слоя может быть reset. Могут быть и другие случаи, в которых это также происходит. Чтобы быть в безопасности, установите масштаб содержимого только после добавления слоя в представление.
Попробуйте назначить основной экран на свой пользовательский уровень во время вашего настраиваемого метода init. В Swift 3 выглядит так:
layer.contentsScale = UIScreen.mainScreen().scale
Или, в Swift 4:
layer.contentsScale = UIScreen.main.scale
После добавления слоя к его суперслою. set shouldRasterize to YES, установить содержимоеScale и 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"];