CGGradient: draw a linear gradient at an angle

I am trying to draw a linear CGGradient at an angle. Since "CGContextDrawLinearGradientWithAngle ()" does not exist, I am trying to use CGContextDrawLinearGradient (CGContextRef, CGGradientRef, CGPoint startPoint, CGPoint endPoint, CGGradientDrawingOptions).

With that in mind, I need to convert the angle (degrees) to the start point and end point. I would like to imitate the NSGradient drawInBezierPath: angle. (The AppGit NSGradient, unfortunately, is not available to iOS developers.) Fortunately, the documentation tells us how to get the initial 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; } 

Unfortunately, the documentation does not indicate how to get the endpoint. (Using either the height or the width of the rectangle, since the distance is enough for certain angles.) Several sites out there tell us how we can find the end point. Unfortunately, the distance must be known before I can calculate the end point. However, the endpoint must be calculated in order to obtain the distance. There is clearly more, as NSGradient seems to have understood.

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

Any ideas.

+4
source share
2 answers

I am dealing with the same problem, a little differently, I use the center point and the corner, and extend the side left and right to find the points on the edge, my problem was that there would be empty space if the angel does not indicate which either the axis and the function's drawing parameter provide "kCGGradientDrawsBeforeStartLocation or kCGGradientDrawsAfterEndLocation", so it looks like one side will be empty.

But it turns out that I can combine the two options with '|', so the problem is solved, here is my code:

 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
source

I'm not 100% sure how this gradient works, but from what you wrote, I assume that you just want the length of the line to start from the moment it hit the rectangle.

If so, you just need to do trigonometry. Lets name distance x and angle a.

Between 0 and 45 degrees: width = xcos (a), so x = width / cos (a)

45 to 90 degress: height = xsin (a), so x = height / sin (a)

From 90 to 135 degrees, we moved to a new angle. Here x = height / cos (a-90).

Between 135 and 180 x = Width / sin (a-90)

Between 180 and 225 we again moved to a corner. Here x = width / cos (a-180).

Between 225 and 270 x = height / sin (a-180)

The last corner! Between 270 and 315 x = height / sin (a-270)

And finally between 315 and 360 x = width / cos (a-270)

Some of them probably simplify, but it’s easiest to think of a line starting in the lower left, pointing to the right and spanning counterclockwise, which appears to be when calculating the starting point.

0
source

Source: https://habr.com/ru/post/1397910/


All Articles