Лучший способ выполнить этот рисунок с помощью Quartz 2D / Core Graphics? - PullRequest
2 голосов
/ 22 апреля 2009

В качестве фона для одного из представлений в моем приложении я хотел бы нарисовать довольно простую прямоугольную границу прямо внутри рамки. По сути, это был бы прямоугольный градиент: черная линия вокруг рамки, которая замирала до белого примерно на 10-20 пикселей. К сожалению, насколько я могу судить, Core Graphics не предоставляет прямоугольные градиенты (с CGGradient или CGShading). Поэтому мне интересно, какой будет лучший подход.

Два, которые приходят мне в голову:

  1. Нарисуйте серию концентрических прямоугольников, каждый из которых по цвету светлее, и вставьте по 1 пикселю с каждой стороны. Я не могу придумать более простой подход, но я должен сам выполнить все вычисления градиента, и это может быть много графических операций.
  2. Используйте CGGradient в линейном режиме, по одному для каждой стороны. Но чтобы это работало, я думаю, мне нужно было бы сначала установить трапециевидную область отсечения для каждой стороны, чтобы градиенты были сглажены по углам.

Похоже, что там должен быть способом использовать обводку для этого, но не похоже, что есть способ определить шаблон, который по-разному ориентирован с каждой стороны.

Ответы [ 2 ]

3 голосов
/ 22 апреля 2009

Я бы выбрал вариант № 2:

Используйте CGGradient в линейном режиме, один раз для каждой стороны. Но для того, чтобы это работало, я думаю, что мне нужно сначала установить трапециевидную область отсечения для каждой стороны, чтобы градиенты были сглажены по углам.

Использование NSBezierPath для создания трапециевидных областей будет довольно простым, и вам нужно будет выполнить только четыре операции рисования.

Вот основной код для создания левой боковой трапеции:

NSRect outer = [self bounds];
NSPoint outerPoint[4];
outerPoint[0] = NSMakePoint(0, 0);
outerPoint[1] = NSMakePoint(0, outer.size.height);
outerPoint[2] = NSMakePoint(outer.size.width, outer.size.height);
outerPoint[3] = NSMakePoint(outer.size.width, 0);

NSRect inner = NSInsetRect([self bounds], borderSize, borderSize);
NSPoint innerPoint[4];
innerPoint[0] = inner.origin;
innerPoint[1] = NSMakePoint(inner.origin.x,
                            inner.origin.y + inner.size.height);
innerPoint[2] = NSMakePoint(inner.origin.x + inner.size.width,
                            inner.origin.y + inner.size.height);
innerPoint[3] = NSMakePoint(inner.origin.x + inner.size.width,
                            inner.origin.y);

NSBezierPath leftSidePath = [[NSBezierPath bezierPath] retain];
[leftSidePath moveToPoint:outerPoint[0]];
[leftSidePath lineToPoint:outerPoint[1]];
[leftSidePath lineToPoint:innerPoint[1]];
[leftSidePath lineToPoint:innerPoint[0]];
[leftSidePath lineToPoint:outerPoint[0]];

// ... etc.

[leftSidePath release];
0 голосов
/ 23 ноября 2009

что-то подобное может также работать. в основном: вместо использования обтравочных контуров, просто используйте blendmode. и в этом примере градиент кэшируется в CGLayer.

 CGContextRef ctx = UIGraphicsGetCurrentContext();
 CGColorSpaceRef cspace = CGColorSpaceCreateDeviceRGB();

 CGContextSetRGBFillColor(ctx, 1.0, 1.0, 1.0, 1.0);
 CGContextFillRect(ctx,self.bounds);

 CGFloat w = self.bounds.size.width;
 CGFloat h = self.bounds.size.height;
 CGFloat dh = (w-h)/2;

 CGLayerRef l = CGLayerCreateWithContext(ctx,CGSizeMake(h,48.0f),NULL);
 CGContextRef lctx = CGLayerGetContext(l);

 float comp[] = { .2,.5,1.0,1.0,1.0,1.0,1.0,1.0};
 CGGradientRef gradient = CGGradientCreateWithColorComponents(cspace, comp, NULL, 2);
 CGContextDrawLinearGradient(lctx, gradient,CGPointMake(0,0),CGPointMake(0,48), 0);

 CGContextSaveGState(ctx);
 CGContextSetBlendMode(ctx,kCGBlendModeDarken);
 for(int n=1;n<5;n++)
 {
  CGContextTranslateCTM(ctx,w/2.0,h/2.0);
  CGContextRotateCTM(ctx, M_PI_2);
  CGContextTranslateCTM(ctx,-w/2.0,-h/2.0);
  CGContextDrawLayerAtPoint(ctx,CGPointMake((n%2)*dh,(n%2)*-dh),l);
 }
 CGContextRestoreGState(ctx);
...