CGGradient: рисование линейного градиента по углу - PullRequest
5 голосов
/ 23 февраля 2012

Я пытаюсь нарисовать линейный CGGradient по углу.Поскольку «CGContextDrawLinearGradientWithAngle ()» не существует, я пытаюсь использовать CGContextDrawLinearGradient (CGContextRef, CGGradientRef, CGPoint startPoint, CGPoint endPoint, CGGradientDrawingOptions).в начальную точку и конечную точку.Я хотел бы имитировать drawInBezierPath: угол NSGradient.(Как часть AppKit, NSGradient, к сожалению, недоступен для разработчиков iOS.) К счастью, документация говорит нам, как получить начальный градиент :

- (CGPoint)startingPointForAngle:(CGFloat)angle rect:(CGRect)rect { 
    CGPoint point = CGPointZero;
    if (angle < 90.0f)
        point = CGPointMake(CGRectGetMinX(rect), CGRectGetMaxY(rect));
    else if (angle < 180.0f)
        point = CGPointMake(CGRectGetMaxX(rect), CGRectGetMaxY(rect));
    else if (angle < 270.0f)
        point = CGPointMake(CGRectGetMaxX(rect), CGRectGetMinY(rect));
    else
        point = CGPointMake(CGRectGetMinX(rect), CGRectGetMinY(rect));

    return point;
}

К сожалению, документация делаетне говорите нам, как получить конечную точку.(Использование высоты или ширины прямоугольника в качестве расстояния достаточно только для определенных углов.) Несколько сайтов говорят нам, как мы можем найти конечную точку.К сожалению, расстояние нужно знать, прежде чем я смогу вычислить конечную точку.Все же конечная точка должна быть вычислена, чтобы получить расстояние.Очевидно, в этом есть нечто большее, поскольку NSGradient, похоже, понял это.

- (CGPoint)endingPointForAngle:(CGFloat)angle rect:(CGRect)rect startingPoint:(CGPoint)startingPoint {
    //http://www.zahniser.net/~russell/computer/index.php?title=Angle%20and%20Coordinates
    //(x + distance * cos(a), y + distance * sin(a))
    CGFloat angleInRadians = (CGFloat)M_PI/180.0f * angle;
    CGFloat distance = ????????;
    CGPoint point = CGPointMake(startingPoint.x + distance * cosf(angleInRadians), startingPoint.y + distance * sinf(angleInRadians));
    return point;
}

CGPoint startingGradientPoint = [self startingPointForAngle:self.fillGradientAngle rect:rect];
CGPoint endingGradientPoint = [self endingPointForAngle:self.fillGradientAngle rect:rect startingPoint:startingGradientPoint];
CGContextDrawLinearGradient(graphicsContext, self.fillGradient, startingGradientPoint, endingGradientPoint, 0);

Любые идеи.

Ответы [ 2 ]

1 голос
/ 16 января 2014

Я имею дело с той же проблемой, немного по-другому, я использую центральную точку и угол, и расширяю сторону влево и вправо, чтобы найти точки на краю, моя проблема была в том, что будет пробел если ангел не указывает на какую-либо ось, а параметр рисования функции предоставляют «kCGGradientDrawsBeforeStartLocation или kCGGradientDrawsAfterEndLocation», поэтому похоже, что одна сторона будет пустой.

Но оказывается, что я могу объединить два варианта с '|', так что проблема решена, вот мой код:

CGGradientRef grRef = CGGradientCreateWithColors(colorSpace,  (__bridge CFArrayRef)gradient.colorArray, NULL);
CGFloat degree = angle * M_PI / 180;
CGPoint center = CGPointMake(width/2, height/2);
CGPoint startPoint = CGPointMake(center.x - cos (degree) * width/2, center.y - sin(degree) * height/2);
CGPoint endPoint = CGPointMake(center.x + cos (degree) * width/2, center.y + sin(degree) * height/2);

NSLog(@"start point:%@ \n, end point: %@",NSStringFromCGPoint(startPoint),NSStringFromCGPoint(endPoint));

CGContextDrawLinearGradient(gradientContext, grRef, startPoint, endPoint, kCGGradientDrawsBeforeStartLocation|kCGGradientDrawsAfterEndLocation);
0 голосов
/ 23 февраля 2012

Я не уверен на 100%, как работает этот градиент, но из того, что вы написали, я предполагаю, что вы просто хотите, чтобы длина линии от начальной точки доходила до края прямоугольника.

Если это так, вам просто нужно сделать тригонометрию.Давайте назовем расстояние x и угол a.

между 0 и 45 градусами: ширина = xcos (a), поэтому x = ширина / cos (a)

между 45 и 90 градусами: высота= xsin (a), поэтому x = высота / грех (a)

Между 90 и 135 градусами мы переместились в новый угол.Здесь x = высота / cos (a-90).

между 135 и 180 x = ширина / грех (a-90)

между 180 и 225 мы снова сдвинули угол.Здесь x = ширина / cos (a-180).

от 225 до 270 x = высота / грех (a-180)

Последний угол!От 270 до 315 x = высота / грех (a-270)

И, наконец, от 315 до 360 x = ширина / cos (a-270)

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

...