CAShapeLayer рисует путь странно - PullRequest
2 голосов
/ 13 декабря 2011

Я создаю UIBezierPath следующим образом:

UIBezierPath *path = [UIBezierPath bezierPath];
CGFloat yOrigin = 2;
for (int i = 0; i < lines; ++i) {
    [path moveToPoint:CGPointMake(0, yOrigin)];
    [path addLineToPoint:CGPointMake(width, yOrigin)];
    yOrigin += distance;
}
[path closePath];

Затем я помещаю его в CAShapeLayer:

CAShapeLayer *shapeLayer = [[CAShapeLayer alloc] init];
[shapeLayer setFrame:aFrame];
[shapeLayer setPath:[bezierPath CGPath]];
[shapeLayer setStrokeColor:[[UIColor blackColor] CGColor]];
[shapeLayer setMasksToBounds:YES];

Однако при добавлении в представление прокруткирезультат:

Path Image

Почему это происходит?Первые четыре строки почти серые!Это похоже на проблему наложения имен, но путь такой простой.

Ответы [ 2 ]

5 голосов
/ 13 декабря 2011

Да, это проблема сглаживания.

Используемый путь имеет ширину 1 пт.В приведенном выше примере три верхних экземпляра CAShapeLayer расположены точно по центру на целой точке, например.5.0, где нижний экземпляр расположен между двумя целыми точками, например.14.5.

Когда система отображает ваши слои на пикселях экранов, она сглаживает первые три линии, рисуя оба затронутых пикселя с прозрачностью 50%.Нижняя линия идеально сидит на пикселе и поэтому нарисована абсолютно черным.

Я надеюсь, что немного ASCII Art поможет понять.

 pt          upper lines                           lower line
5.0|---------                                      -------------------------------
   |  pixel  --------------------------------------  perfectly aligned center 5.5
6.0|---------  line between pixels centered on 6.0 -------------------------------
   |  pixel  --------------------------------------
7.0|---------
0 голосов
/ 01 сентября 2013

У меня такая же ситуация: вертикальные и горизонтальные черные линии становятся серыми.

Похоже, что "привязанные" координаты UiView для пикселей, а не CALayer.

Мое решение этой проблемы состоит в том, чтобыдобавить 0,5 на coodinates.

CGRect bounds_on_pixels(const CGRect& bounds) {

    const float f = 0.5f;
    return CGRectMake(bounds.origin.x+f, bounds.origin.y+f, bounds.size.width-1.f, bounds.size.height-1.f);
}

Примечание: -1.f по размеру является факультативным.

Пример использования с CAShapeLayer и UIBezierPath

CAShapeLayer* shape_layer = [CAShapeLayer layer];
// initialize shape_layer...
shape_layer.path =
[
 UIBezierPath bezierPathWithRoundedRect:bounds_on_pixels(self.view.bounds)
 byRoundingCorners:UIRectCornerTopLeft | UIRectCornerTopRight
 cornerRadii:CGSizeMake(10.0, 10.0)
].CGPath;
// add shape_layer: [self.view.layer insertSublayer:shape_layer atIndex:0];

@ tonklon: спасибо за идею!

...