CGGradient:在一个角度上绘制线性渐变

时间:2012-02-22 22:24:45

标签: iphone objective-c ios core-graphics

我试图在一个角度上绘制线性CGGradient。因为“CGContextDrawLinearGradientWithAngle()”不存在,我试图使用CGContextDrawLinearGradient(CGContextRef,CGGradientRef,CGPoint startPoint,CGPoint endPoint,CGGradientDrawingOptions)。

考虑到这一点,我需要将角度(度)转换为起点和终点。我想模仿NSGradient的drawInBezierPath:angle。 (作为AppKit的一部分,很难让iOS开发人员无法使用NSGradient。)幸运的是,文档告诉我们如何get the starting gradient

- (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;
}

不幸的是,文档没有告诉我们如何获得结束点。 (使用矩形的高度或宽度,因为距离仅适用于某些角度。)Several sites out there告诉我们如何找到终点。不幸的是,在我计算结束点之前需要知道距离。然而,需要计算结束点以获得距离。显然还有更多,因为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 个答案:

答案 0 :(得分:1)

我正在处理相同的问题,用一点点不同的方式,我使用中心点和角度,并向左和向右延伸以找到边缘上的点,我的问题是会有白色空间如果天使没有指向任何轴,并且绘图选项函数提供了“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);

答案 1 :(得分:0)

我不是百分之百地确定这个渐变的东西是如何起作用的,但是根据你所写的内容,我假设你基本上只想要一条直线的长度,从起点到撞击矩形的一边。 / p>

如果是这种情况,您只需要做一些三角函数。让我们调用距离x和角度a。

在0到45度之间:width = xcos(a)所以x = width / cos(a)

在45到90度之间:身高= xsin(a)所以x =身高/罪(a)

在90到135度之间,我们已经搬到了一个新角落。这里x =高度/余弦(a-90)。

135到180 x =宽度/ sin(a-90)

在180到225之间,我们再次移动角落。这里x =宽度/余弦(a-180)。

225到270 x =高度/ sin(a-180)

最后一个角落!在270和315 x之间=高度/ sin(a-270)

最后介于315和360 x之间=宽度/ cos(a-270)

其中一些可能会简化,但最简单的方法是考虑左下角开始指向右侧并沿逆时针方向扫过的线,这似乎是在您的起点计算中发生的。