2014-09-09 1 views
16

У меня есть пользовательский UIView, который рисует что-то в перезаписанногоIOS рисунок в CALayers drawInContext либо некачественно или размыто на сетчатке

- (void)drawRect:(CGRect)rect 

это прекрасно работает и дает точные результаты на экранах сетчатки глаза.

Однако, теперь я хотел бы сделать свойства, на которых рисунок основан на анимации. Создание Animatable свойств представляется возможным только на CALayer, поэтому вместо того, чтобы делать рисунок в UIView, создать пользовательский CALayer подкласс и сделать рисунок внутри

- (void) drawInContext:(CGContextRef)ctx 

Я использую довольно много и тот же код рисования в этом как я использовал в функции drawRect пользовательского UIView.

Результат выглядит так же, - однако, это не сетчатка разрешение, но неровной (большие квадратные пиксели)

если я ставлю

self.contentsScale = [UIScreen mainScreen].scale; 

К началу моей реализации drawInContext, то вместо некачественно результат, я получаю размытый результат (как будто рендеринг по-прежнему выполняется без разрешения сетчатки, а затем масштабируется до разрешения сетчатки).

Каков правильный способ визуализации острых путей сетчатки в CALayers drawInContext?

вот некоторые скриншоты (синяя линия является частью пользовательского чертежа в вопросе желтая часть всего изображения.)

Нарисованные внутри DrawRect пользовательских UIView в:

enter image description here

Нарисованные внутри пользовательских CALayer в drawInContext:

enter image description here

Drawin внутри drawInContext пользовательских CALayer, в с первой установкой self.contentScale:

enter image description here

Для полноты здесь (урезанная версия) кода рисования:

//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

+0

в сетчатке дисплей, вам нужно умножить ширину и высоту на 2. – Bejibun

+0

нет, размер и расположение на экране правильно – user1282931

+0

Я имею в виду экран вы просто создаете, должны быть умножены на 2, потому что дисплей сетчатки требует двойного разрешения. – Bejibun

ответ

8

Используете ли вы shouldRasterize = YES в слое? Попробуйте выполнить рисование в подклассе CALayer, но установите rasterizationScale на шкалу экрана.

+0

должен был установить растеризациюScale на экран масштаба * 4.0, чтобы получить smooooth строки ... –

+0

@ AndresCanella, на каком устройстве вы использовали 4.0 для растеризацииScale? – Crashalot

+0

@Crashalot Я закончил использовать масштаб экрана * 2.0 на i6. Я потерял четкость на 4.0. –

3

Вопрос, скорее всего, будет contentScale здесь; имейте в виду, что если вы назначаете это настраиваемому представлению, переопределяя его функцию layerClass, масштаб содержимого может быть сброшен. Могут быть и другие случаи, в которых это также происходит. Чтобы быть в безопасности, установите масштаб содержимого только после добавления слоя в представление.

Попробуйте назначить масштаб основного экрана на свой пользовательский уровень во время метода инициализации настраиваемого вида.В Swift 3, выглядит следующим образом:

layer.contentsScale = UIScreen.mainScreen().scale 

Или в Swift 4:

layer.contentsScale = UIScreen.main.scale 
+0

Хороший улов! Спасибо чувак –

3

После добавления слоя к его superlayer. установить 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"]; 
Смежные вопросы