CAGradientLayer with Angle - ios

I am drawing CGPath which is not rectangle or square,and adding CGPath to CAShapeLayer. This CAShapeLayer's frame getting from CGPath using CGPathGetBoundingBox(path). So it will be rectangle or square. Now i want to set gradient color to layer but my path is not rectangle or square so it is not spreading gradient color equally in whole CGPath. Is there any way to set gradient color to CGPath or how can i set gradient color with angle?
Please refer screen shot to understand situation. Here white color indicates frame of CGPath and green colour, that is our drawn CGPath. At the bottom of CGPath you can see white gradient colour which is not distributed equally in CGPath.

The start and end points of a linear gradient are specified in points relative to the whole size of the layer, with (0,0) at the top left and (1,1) at the bottom right.
Therefore, to make a linear gradient at an angle, you simply need to set the start and end points appropriately. For example, If you used (0,0) and (1,1) as the start and end points, the gradient would run from the top left to the bottom right, at a 45 degree angle.
Working out the specific start and end points for your needs is therefore just a matter of trigonometry.

Related

Swift/ios wave fill animation inside custom layer/shape

I am trying to achieve a fill animation similar to the GIF below but inside a non circular boundary similar to the second image. Can this be done over a UIImage of just the drop?
Sure, you could do that with a CAShapeLayer where you animate the path that draws the shape. You'd then add a mask layer to the shape layer that masks it to the shape of the drop, (which would be another shape layer in the shape of your drop.)
You should be able to get the shape of the wave with a single cubic bezier curve, as wide as the widest part of the area you're filling. You'd create a closed shape that was your wave curve, then the sides and bottom of a rectangle to create a closed shape.
For the wave animation I would suggest a closed UIBezierPath that is 3 sides of a rectangle, followed by a cubic bezier curve who's start and end where on the top corners of your rectangle, and the middle two control points were at 1/4 and 3/4 of the way along the rectangle in the X dimension. Make one of those control points above the top line of your box, and the other below the top line. The animation would just be switching the Y positions of the 2 middle control points of the bezier curve.
Here is what the shape looks like in Photoshop:
Make that bezier path wider than your drop shape, so the ends of the top curve that don't move are out of view.
You'd install the CGPath of that bezier path into a CAShapeLayer. You'd then add a repeating, auto-reversing CABasicAnimation to the shape layer that would swap the Y positions of the two middle control points of the top curve, so the wave peaks and troughs would switch.
Next, you'd create a second CAShapeLayer that would contain a closed drop shape, and install the drop shape layer as a mask on the wave layer.
Finally, as you change your slider, you'd shift the Y position of your entire wave shape layer up and down.

Swift 3, draw circle with special lineCap

Currently I'm using CAShapeLayer and UIBezierPath to draw a line for avatar. It's Ok for the normal one with lineCap = kCALineCapRound. BUT I've been STRUGGLING to draw line with START and END lineCap like image below:
You can't draw this circle with a shape layer, because a shape layer supports only one single stroke color. You should write your own layer class where you should draw three separate circle segments with kCALineCapRound:
A full yellow circle.
Draw the blue segment over the yellow circle. It is visible and you can see the rounded ends.
Draw a segment of the yellow circle, say 5 degrees of the top. Then you can also see the rounded end of the yellow line.
You should use CGPath and CGContext instead of UIBezierPath.

Rounded Rectangle In Delphi

i have been trying to draw a rounded rectangle with spacing in the border, but i cant seem to find a way to do this using the Canvas.RoundRect function, and i am not that good in maths to draw the edges myself, i can draw a rectangle with spacing using the Canvas.MoveTo and Canvas.LineTo functions, but i dont know how to make the edges rounded. Currently what i am doing is i make yellow rectangle at the place where i want to make the spacing in the border but the problem is when i am printing i have to directly draw on printer canvas and i have to draw on a transparent sheet, so a background color will cause problems. Anyone who can help me build a custom drawing routine or tell me how can i erase that area and still print on a transparent paper without any background color. The yellow background color is just for a preview, when i am drawing to a printer canvas the background is transparent.
See the image to know what i mean by spacing in the border line.
Thanks
You can exclude the gap by manipulating the clipping region of the current device context. Assuming that L, R, T and B are the coordinates of your yellow rectangle to make the gap, use the following code:
ExcludeClipRect(Canvas.Handle, L, T, R, B); // exclude the gap
Canvas.RoundRect(<whatever you already do here>);
SelectClipRgn(Canvas.Handle, 0); // reset the clipping region
You can draw your partial rounded rectangle yourself. Use MoveTo and LineTo for the straight portions, and use Arc for the corners.
The Arc function draws a portion of an ellipse. The first two pairs of coordinates to the function indicate the bounds of the ellipse. If you want the corners of your rectangle to be circular, then the ellipse is a circle, and X2 - X1 will equal Y2 - Y1. The second two pairs of coordinates indicate the starting and ending points on the circle; they'll be the same points you pass to MoveTo and LineTo for the straight portions. The arc is drawn counter-clockwise.

Cocoa CoreGraphics: How to fill multiple shapes with a gradient

I have logo text drawn as shapes (closed CGBezierPaths) that I want to fill with a gradient.(Light at the top, moving to dark at the bottom) How can I fill each shape with gradient such that the gradient is the same color for each shape.
The problem is drawing the gradient for each shape, if the letters are different height then the gradient has a different ramp since the distance is smaller. Hope that makes sense.
So basically I want draw a single gradient down the rect and use all the shapes as a clipping mask. Is this possible?
For gradient drawing - take a look at this project:
https://github.com/wczekalski/CDPieMenu
It creates gradient using two colors programmatically.

what is the relationship between image edges and gradient?

Is there anybody can help me interpret
"Edge points may be located by the maxima of the
module of the gradient, and the direction of edge contour is orthogonal to the direction of the gradient."
Paul R has given you an answer, so I'll just add some images to help make the point.
In image processing, when we refer to a "gradient" we usually mean the change in brightness over a series of pixels. You can create gradient images using software such as GIMP or Photoshop.
Here's an example of a linear gradient from black (left) to white (right):
The gradient is "linear" meaning that the change in intensity is directly proportional to the distance between pixels. This particular gradient is smooth, and we wouldn't say there is an "edge" in this image.
If we plot the brightness of the gradient vs. X-position (left to right), we get a plot that looks like this:
Here's an example of an object on a background. The edges are a bit fuzzy, but this is common in images of real objects. The pixel brightness does not change from black to white from one pixel to the next: there is a gradient that includes shades of gray. This is not obvious since you typically have to zoom into a photo to see the fuzzy edge.
In image processing we can find those edges by looking at sharp transitions (sharp gradients) from one brightness to another. If we zoom into the upper left corner of that box, we can see that there is a transition from white to black over just a few pixels. This transition is a gradient, too. The difference is that the gradient is located between two regions of constant color: white on the left, black on the right.
The red arrow shows the direction of the gradient from background to foreground: pixels are light on the left, and as we move in the +x direction the pixels become darker. If we plot the brightness sampled along the arrow, we'll get something like the following plot, with red squares representing the brightness for a specific pixel. The change isn't linear, but instead will look like one side of a bell curve:
The blue line segment is a rough approximation of the slope of the curve at its steepest. The "true" edge point is the point at which slope is steepest along the gradient corresponding to the edge of an object.
Gradient magnitude and direction can be calculated using horizontal and vertical Sobel filters. You can then calculate the direction of the gradient as:
gradientAngle = arctan(gradientY / gradientX)
The gradient will be steepest when it is perpendicular to the edge of the object.
If you look at some black and white images of real scenes, you can zoom in, look at individual pixel values, and develop a good sense of how these principles apply.
Object edges typically result in a step change in intensity. So if you take the derivative of intensity it will have a large (positive or negative) value at edges and a smaller value elsewhere. If you can identify the direction of steepest gradient then this will be at right angles to (orthogonal to) the object edge.

Resources