Draw gradient under UIBezierPath - ios

I have drawn a curved line. I want to put a gradient from the view all the way up to the line (so that the gradient curves along with the line.)
edit: here is a photo of what the code below produces:
I know how to draw the line, and I know how to add a regular gradient, but just not the two together. Here is my code:
override func drawRect(rect: CGRect) {
// draw the curved line, this code works just fine.
let path1 = UIBezierPath()
path1.lineWidth = 1.1
UIColor.greenColor().setStroke()
path1.moveToPoint(CGPoint(x: 0, y: bounds.height/2))
path1.addQuadCurveToPoint(CGPoint(x: bounds.width, y: bounds.height/2), controlPoint: CGPoint(x: bounds.width/2, y: (bounds.height * 0.75)))
path1.stroke()
// my attempt to draw the gradient:
let gradient = CAGradientLayer()
gradient.startPoint = CGPoint(x: 1, y: 1)
gradient.endPoint = CGPoint(x: 0, y: 0)
let colors = [UIColor.whiteColor().CGColor, UIColor(red: 0, green: 1, blue: 1, alpha: 0.4).CGColor]
gradient.colors = colors
// the following line is where I need help
gradient.frame = CGRectMake(0, 475, bounds.width, path1.bounds.height)
layer.addSublayer(gradient)
}
what can I set gradient.frame equal to so that it's upper limit is the previously drawn path? Answer in Swift please (i've seen a lot of other questions on this subject but they are all in objective C)
Thanks

I have found the answer.
The following code gave me this:
.
Here is the code:
override func drawRect(rect: CGRect) {
//draw the line of UIBezierPath
let path1 = UIBezierPath()
path1.lineWidth = 1.1
UIColor(white: 1, alpha: 1).setStroke()
path1.moveToPoint(CGPoint(x: 0, y: bounds.height/2))
path1.addQuadCurveToPoint(CGPoint(x: bounds.width, y: bounds.height/2), controlPoint: CGPoint(x: bounds.width/2, y: (bounds.height * 0.65)))
path1.stroke()
// add clipping path. this draws an imaginary line (to create bounds) from the
//ends of the UIBezierPath line down to the bottom of the screen
let clippingPath = path1.copy() as! UIBezierPath
clippingPath.addLineToPoint(CGPoint(x: self.bounds.width, y: self.bounds.height))
clippingPath.addLineToPoint(CGPoint(x: 0, y: bounds.height))
clippingPath.closePath()
clippingPath.addClip()
// create and add the gradient
let colors = [UIColor(red: 0, green: 1, blue: 1, alpha: 0.45).CGColor, UIColor.whiteColor().CGColor]
let colorSpace = CGColorSpaceCreateDeviceRGB()
let colorLocations:[CGFloat] = [0.0, 1.0]
let gradient = CGGradientCreateWithColors(colorSpace,
colors,
colorLocations)
let context = UIGraphicsGetCurrentContext()
let startPoint = CGPoint(x: 1, y: 1)
let endPoint = CGPoint(x: 1, y: bounds.maxY)
// and lastly, draw the gradient.
CGContextDrawLinearGradient(context, gradient, startPoint, endPoint, CGGradientDrawingOptions.DrawsAfterEndLocation)
}

Related

Draw Triangle With Curved Side And Straight Sides Using UIBezierPath and CAShapeLayer In Swift

Background
I have some simple code that draws a triangle with three straight sides using UIBezierPath and CAShapeLayer. The result is in image A, below.
However, I want the longest side of the triangle to have an inwards curve. The desired result is in image B, below.
Question
What change to the code below can achieve the longest side of the triangle to have an inwards curve? How do I instruct the path to curve?
Code
func drawShape() {
let path1 = UIBezierPath()
path1.move(to: CGPoint(x: 50, y: 600))
path1.addLine(to: CGPoint(x: 300, y: 600))
path1.addLine(to: CGPoint(x: 300, y: 50))
path1.close()
let shape1 = CAShapeLayer()
shape1.path = path1.cgPath
shape1.fillColor = UIColor(red: 0.5, green: 0.5, blue: 0.5, alpha: 1).cgColor
view.layer.insertSublayer(shape1, at: 1)
}
Image
I have added addQuadCurve before closing the path. It gives the desired result.
Code
func drawShape() {
let path1 = UIBezierPath()
path1.move(to: CGPoint(x: 50, y: 600))
path1.addLine(to: CGPoint(x: 300, y: 600))
path1.addLine(to: CGPoint(x: 300, y: 50))
path1.addQuadCurve(to: CGPoint(x: 50, y: 600), controlPoint: CGPoint(x: (300-50), y: (600*0.5)))
path1.close()
let shape1 = CAShapeLayer()
shape1.path = path1.cgPath
shape1.fillColor = UIColor(red: 0.5, green: 0.5, blue: 0.5, alpha: 1).cgColor
view.layer.insertSublayer(shape1, at: 1)
}
Image

gradient in for multipel UIBezierPath

I'm supposed to create this.
I did search the google, youtube, and StackOverflow, and the code below is the result of my research.
#IBDesignable class TriangleView2: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
let gradient = CAGradientLayer()
override func draw(_ rect: CGRect) {
//draw the line of UIBezierPath
let path1 = UIBezierPath()
path1.move(to: CGPoint(x: rect.minX - 100, y: rect.maxY - 80))
path1.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
path1.addLine(to: CGPoint(x: (rect.maxX + 90 ), y: rect.minY/2 ))
path1.close()
// add clipping path. this draws an imaginary line (to create bounds) from the
//ends of the UIBezierPath line down to the bottom of the screen
let clippingPath = path1.copy() as! UIBezierPath
clippingPath.move(to: CGPoint(x: rect.minX - 100, y: rect.maxY - 80))
clippingPath.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
clippingPath.addLine(to: CGPoint(x: (rect.maxX + 90 ), y: rect.minY/2 ))
clippingPath.close()
clippingPath.addClip()
// create and add the gradient
let colors = [theme.current.profile_start_view1.cgColor, theme.current.profile_end_view1.cgColor]
let colorSpace = CGColorSpaceCreateDeviceRGB()
let colorLocations:[CGFloat] = [0.0, 1.0]
let gradient = CGGradient(colorsSpace: colorSpace,
colors: colors as CFArray,
locations: colorLocations)
let context = UIGraphicsGetCurrentContext()
let startPoint = CGPoint(x: 1, y: 1)
let endPoint = CGPoint(x: 1, y: bounds.maxY)
// and lastly, draw the gradient.
context!.drawLinearGradient(gradient!, start: startPoint, end:
endPoint, options: CGGradientDrawingOptions.drawsAfterEndLocation)
}
}
Right not I have 2 views ( will be 3 if I could complete it) with some differences.
The result is this.
These 2 views do not have the same colour, but as you can see both views have the same gradient with the same direction.
Does anyone have any suggestion?
This is somewhat similar to Codo's answer but you only need 4 points.
class FourGradientsView: UIView {
override func draw(_ rect: CGRect) {
let ctx = UIGraphicsGetCurrentContext()!
// Points of area to draw - adjust these 4 variables as needed
let tl = CGPoint(x: 0, y: 0)
let tr = CGPoint(x: bounds.width * 1.3, y: 0)
let bl = CGPoint(x: -bounds.width * 1.8, y: bounds.height * 1.4)
let br = CGPoint(x: bounds.width * 1.3, y: bounds.height * 2)
// Find the intersection of the two crossing diagonals
let s1x = br.x - tl.x
let s1y = br.y - tl.y
let s2x = tr.x - bl.x
let s2y = tr.y - bl.y
//let s = (-s1y * (tl.x - bl.x) + s1x * (tl.y - bl.y)) / (-s2x * s1y + s1x * s2y)
let t = ( s2x * (tl.y - bl.y) - s2y * (tl.x - bl.x)) / (-s2x * s1y + s1x * s2y)
let center = CGPoint(x: tl.x + (t * s1x), y: tl.y + (t * s1y))
// Create clipping region to avoid drawing where we don't want any gradients
ctx.saveGState()
let clip = CGPoint(x: 0, y: bounds.height * 0.7)
let clipPath = UIBezierPath()
clipPath.move(to: CGPoint(x: 0, y: 0))
clipPath.addLine(to: clip)
clipPath.addLine(to: CGPoint(x: bounds.width, y: bounds.height))
clipPath.addLine(to: CGPoint(x: bounds.width, y: 0))
clipPath.close()
clipPath.addClip()
// Use these two colors for all 4 gradients (adjust as needed)
let colors = [
UIColor(hue: 120/360, saturation: 1, brightness: 0.85, alpha: 1).cgColor,
UIColor(hue: 120/360, saturation: 1, brightness: 0.3, alpha: 1).cgColor
] as CFArray
// The common gradient
let gradient = CGGradient(colorsSpace: CGColorSpaceCreateDeviceRGB(), colors: colors, locations: nil)!
// Top gradient
ctx.saveGState()
let pathTop = UIBezierPath()
pathTop.move(to: tl)
pathTop.addLine(to: tr)
pathTop.addLine(to: center)
pathTop.close()
pathTop.addClip()
ctx.drawLinearGradient(gradient, start: CGPoint(x: bounds.width, y: 0), end: CGPoint(x: 0, y: 0), options: [])
ctx.restoreGState()
// Right gradient
ctx.saveGState()
let pathRight = UIBezierPath()
pathRight.move(to: tr)
pathRight.addLine(to: br)
pathRight.addLine(to: center)
pathRight.close()
pathRight.addClip()
ctx.drawLinearGradient(gradient, start: CGPoint(x: bounds.width, y: bounds.height), end: CGPoint(x: bounds.width, y: 0), options: [])
ctx.restoreGState()
// Bottom gradient
ctx.saveGState()
let pathBottom = UIBezierPath()
pathBottom.move(to: br)
pathBottom.addLine(to: bl)
pathBottom.addLine(to: center)
pathBottom.close()
pathBottom.addClip()
ctx.drawLinearGradient(gradient, start: CGPoint(x: 0, y: bounds.height), end: CGPoint(x: bounds.width, y: bounds.height), options: [])
ctx.restoreGState()
// Left gradient
ctx.saveGState()
let pathLeft = UIBezierPath()
pathLeft.move(to: tl)
pathLeft.addLine(to: bl)
pathLeft.addLine(to: center)
pathLeft.close()
pathLeft.addClip()
ctx.drawLinearGradient(gradient, start: CGPoint(x: 0, y: 0), end: CGPoint(x: 0, y: bounds.height), options: [])
ctx.restoreGState()
ctx.restoreGState()
}
}
let grView = FourGradientsView(frame: CGRect(x: 0, y: 0, width: 320, height: 320))
grView.backgroundColor = .black
You wrote code that always uses the same start and end color, always uses the same color locations, and always uses the same start and end points. Of course the gradients have the same gradient with the same direction.
Give your views gradient start point and end point properties as well as start and end colors. Set the gradient start points for your gradient views in your view controller's layoutDidChange() method, based on the bounds of the views. (That way you handle device rotation and different sized devices correctly.
Here's an example that you can run directly in the playground.
As you want four gradients and as gradients are draw using clipping, the graphics context is saved and restored several times (to reset the clipping).
The grading start and end point is one of the clipping corners. That's not needed. You can (and probably) should use separate points. To achieve the desired result, you sometimes want to use a start or end point considerably outside the the clipping area.
import UIKit
import PlaygroundSupport
class TriangleView2: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func draw(_ rect: CGRect) {
let colors = [UIColor(red: 50/255.0, green: 242/255.0, blue: 111/255.0, alpha: 1).cgColor,
UIColor(red: 29/255.0, green: 127/255.0, blue: 60/255.0, alpha: 1).cgColor]
let colorSpace = CGColorSpaceCreateDeviceRGB()
let colorLocations:[CGFloat] = [0.0, 1.0]
let gradient = CGGradient(colorsSpace: colorSpace,
colors: colors as CFArray,
locations: colorLocations)!
let options: CGGradientDrawingOptions = [CGGradientDrawingOptions.drawsBeforeStartLocation, CGGradientDrawingOptions.drawsAfterEndLocation]
let p1 = CGPoint(x: 0, y: 0)
let p2 = CGPoint(x: bounds.width, y: 0)
let p3 = CGPoint(x: bounds.width, y: 20)
let p4 = CGPoint(x: bounds.width / 3, y: 140)
let p5 = CGPoint(x: 0, y: 200)
let p6 = CGPoint(x: bounds.width * 5 / 8, y: 260)
let p7 = CGPoint(x: 0, y: 230)
let p8 = CGPoint(x: bounds.width, y: 280)
let context = UIGraphicsGetCurrentContext()!
context.saveGState()
let path1 = UIBezierPath()
path1.move(to: p1)
path1.addLine(to: p2)
path1.addLine(to: p3)
path1.addLine(to: p4)
path1.close()
path1.addClip()
context.drawLinearGradient(gradient, start: p3, end: p1, options: options)
context.restoreGState()
context.saveGState()
let path2 = UIBezierPath()
path2.move(to: p1)
path2.addLine(to: p4)
path2.addLine(to: p5)
path2.close()
path2.addClip()
context.drawLinearGradient(gradient, start: p1, end: p5, options: options)
context.restoreGState()
context.saveGState()
let path3 = UIBezierPath()
path3.move(to: p3)
path3.addLine(to: p8)
path3.addLine(to: p6)
path3.addLine(to: p4)
path3.close()
path3.addClip()
context.drawLinearGradient(gradient, start: p8, end: p3, options: options)
context.restoreGState()
context.saveGState()
let path4 = UIBezierPath()
path4.move(to: p5)
path4.addLine(to: p4)
path4.addLine(to: p6)
path4.addLine(to: p7)
path4.close()
path4.addClip()
context.drawLinearGradient(gradient, start: p7, end: p6, options: options)
context.restoreGState()
}
}
let main = TriangleView2(frame: CGRect(x: 0, y: 0, width: 320, height: 500))
PlaygroundPage.current.liveView = main
Update
One more thing: Do not use the rect parameter to derive the geometry of your shapes. rect does not refer to the view size or position. Instead, it's area that needs to be redrawn. If iOS decides only part of your view needs to be redrawn, your code will draw the wrong shape.

What would be equal in Swift to draw path/rect with a specific color

in Android (in Java) I could do something like this (here I tried to draw Triangle figure which is filled with different colors, first half with red color and second with green, also black stroke around Triangle figure:
#Override
public void onDraw(Canvas canvas) {
....
canvas.clipPath(pathBoundary); // triangle figure path
canvas.drawPath(pathBoundary, paintBlack); // draw black stroke around figure
canvas.drawRect(rectRed, paintRed); // fill first half with red color
canvas.drawRect(rectGreen, paintGreen); // fill second half with green color
in iOS I just learned how to draw Triangle figure with only one color, would like to also draw with two colors (like in Android)
override func draw(_ rect: CGRect) {
guard let context = UIGraphicsGetCurrentContext() else { return }
context.beginPath()
context.move(to: CGPoint(x: rect.minX, y: rect.maxY))
context.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
context.addLine(to: CGPoint(x: (rect.maxX / 2.0), y: rect.minY))
context.setFillColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 0.60)
context.fillPath()
context.clip()
... how to draw path with specific color?
... how to draw rect with specific color?
You can do just like you do on Android: stroke the triangle path, set it as clipping path, stroke a rectangle in red, stroke a rectangle in green.
UIGraphicsBeginImageContext(CGSize(width: 200, height: 200))
let context = UIGraphicsGetCurrentContext()!
context.beginPath()
context.move(to: CGPoint(x: 100, y: 0))
context.addLine(to: CGPoint(x: 0, y: 200))
context.addLine(to: CGPoint(x: 200, y: 200))
context.closePath()
let path = context.path!
context.setStrokeColor(UIColor.black.cgColor)
context.strokePath()
context.addPath(path)
context.clip()
context.setFillColor(UIColor.red.cgColor)
context.fill(CGRect(x: 0, y: 0, width: 200, height: 150))
context.setFillColor(UIColor.green.cgColor)
context.fill(CGRect(x: 0, y: 150, width: 200, height: 50))
let image = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
You can run the code above in a playground. In the right column hover over the last line (the one for image), click on the eye icon and you'll see a preview of the image that was drawn.
The way you do it is basically by drawing two different paths. Each with a different fill color. Here is an example:
override func draw(_ rect: CGRect) {
super.draw(rect)
guard let context = UIGraphicsGetCurrentContext() else { return }
let leftVertex = CGPoint(x: rect.minX, y: rect.maxY)
let topVertex = CGPoint(x: rect.midX, y: rect.minY)
let r = sqrt(pow(leftVertex.x - topVertex.x, 2) + pow(leftVertex.y - topVertex.y, 2))
let leftAngle = atan(rect.maxY/rect.midX)
context.beginPath()
context.move(to: leftVertex)
context.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
context.addLine(to: topVertex)
context.closePath()
context.setFillColor(red: 0.0, green: 1.0, blue: 0.0, alpha: 1)
context.fillPath()
let smallLeftVertex = CGPoint(x: r/2*cos(leftAngle), y: rect.midY)
context.beginPath()
context.move(to: smallLeftVertex)
context.addLine(to: topVertex)
context.addLine(to: CGPoint(x: rect.maxX - smallLeftVertex.x, y: rect.midY))
context.closePath()
context.setFillColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1)
context.fillPath()
}
There is some math to evaluate which would be the vertices of the inner (smaller) triangle.
Here is the result:
If you want you can try it in a playground:
//: Playground - noun: a place where people can play
import UIKit
class TriangleView: UIView {
override func draw(_ rect: CGRect) {
super.draw(rect)
guard let context = UIGraphicsGetCurrentContext() else { return }
let leftVertex = CGPoint(x: rect.minX, y: rect.maxY)
let topVertex = CGPoint(x: rect.midX, y: rect.minY)
let r = sqrt(pow(leftVertex.x - topVertex.x, 2) + pow(leftVertex.y - topVertex.y, 2))
let leftAngle = atan(rect.maxY/rect.midX)
context.beginPath()
context.move(to: leftVertex)
context.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
context.addLine(to: topVertex)
context.closePath()
context.setFillColor(red: 0.0, green: 1.0, blue: 0.0, alpha: 1)
context.fillPath()
let smallLeftVertex = CGPoint(x: r/2*cos(leftAngle), y: rect.midY)
context.beginPath()
context.move(to: smallLeftVertex)
context.addLine(to: topVertex)
context.addLine(to: CGPoint(x: rect.maxX - smallLeftVertex.x, y: rect.midY))
context.closePath()
context.setFillColor(red: 1.0, green: 0.0, blue: 0.0, alpha: 1)
context.fillPath()
}
}
let triangle = TriangleView(frame: CGRect(x: 0, y: 0, width: 100, height: 100))
triangle.backgroundColor = .white
**
Edit:
**
You can also avoid to draw two overlapping triangles by using the clip feature of CGContext. In this case the code would look like this:
override func draw(_ rect: CGRect) {
super.draw(rect)
guard let context = UIGraphicsGetCurrentContext() else { return }
let leftVertex = CGPoint(x: rect.minX, y: rect.maxY)
let topVertex = CGPoint(x: rect.midX, y: rect.minY)
var path = CGMutablePath()
path.move(to: leftVertex)
path.addLine(to: CGPoint(x: rect.maxX, y: rect.maxY))
path.addLine(to: topVertex)
path.closeSubpath()
context.addPath(path)
context.clip()
context.setFillColor(red: 1, green: 0, blue: 0, alpha: 1)
context.fill(CGRect(x: 0, y: 0, width: rect.width, height: rect.height/2))
context.setFillColor(red: 0, green: 1, blue: 0, alpha: 1)
context.fill(CGRect(x: 0, y: rect.midY, width: rect.width, height: rect.height/2))
}
In the first part of the code we create the triangle, we extract the path just drown in the context and we add it as clipping path. Then we can fill the two rectangles with the two different colours.
Hope this answers your question.

How to gradient fill custom UIView using Swift?

I have a custom triangle UIView which I want to fill with custom gradient color.
override func draw(_ rect: CGRect) {
let widerStartingPoint = CGFloat(240)
guard let context = UIGraphicsGetCurrentContext() else { return }
context.beginPath()
context.move(to: CGPoint(x: rect.minX - widerStartingPoint, y: rect.maxY))
context.addLine(to: CGPoint(x: rect.maxX + widerStartingPoint, y: rect.maxY))
context.addLine(to: CGPoint(x: (rect.maxX / 2.0), y: rect.minY))
context.closePath()
let colors = [firstColor.cgColor, secondColor.cgColor ,thirdColor.cgColor] as CFArray
let colorSpace = CGColorSpaceCreateDeviceRGB()
let colorLocations: [CGFloat] = [0.0, 0.5 ,1.0]
let startPoint = CGPoint.zero
let endPoint = CGPoint(x: 0, y: bounds.height)
let gradient = CGGradient(colorsSpace: colorSpace,
colors: colors as CFArray,
locations: colorLocations)!
// I need to find a way to change below color with gradient color
context.setFillColor(red: 1.0, green: 0.5, blue: 0.0, alpha: 0.60)
context.fillPath()
}
I tried to find other setFillColor methods, but they are only allowing assigning single color.
Thank you for your time.
Instead of using setFillColor I used context.drawLinearGradient(gradient, start: startPoint, end: endPoint, options: []) also added clipping to the path. So working code is below!:
override func draw(_ rect: CGRect) {
let widerStartingPoint = CGFloat(240)
guard let context = UIGraphicsGetCurrentContext() else { return }
context.beginPath()
context.move(to: CGPoint(x: rect.minX - widerStartingPoint, y: rect.maxY))
context.addLine(to: CGPoint(x: rect.maxX + widerStartingPoint, y: rect.maxY))
context.addLine(to: CGPoint(x: (rect.maxX / 2.0), y: rect.minY))
context.closePath()
// This was missing!
context.clip()
let colors = [firstColor.cgColor, secondColor.cgColor ,thirdColor.cgColor] as CFArray
let colorSpace = CGColorSpaceCreateDeviceRGB()
let colorLocations: [CGFloat] = [0.0, 0.5 ,1.0]
let startPoint = CGPoint.zero
let endPoint = CGPoint(x: 0, y: bounds.height)
let gradient = CGGradient(colorsSpace: colorSpace,
colors: colors as CFArray,
locations: colorLocations)!
// Also used this method
context.drawLinearGradient(gradient, start: startPoint, end: endPoint, options: [])
context.fillPath()
}

Gradient over UIImageView

I've been trying to fill an image view with a gradient layer, but I can't seem to make it work, I tried to create CAGradientLayer, applied 2 colors on it then applied it as a mask to the main image layer.
let gradient = CAGradientLayer()
gradient.frame = (self.imageView?.bounds)!
gradient.colors = [UIColor.blue.cgColor, UIColor.purple.cgColor]
gradient.startPoint = CGPoint(x: 0.0, y: 0.5)
gradient.endPoint = CGPoint(x: 0.5, y: 1.0)
gradient.locations = [0, 1]
self.imageView?.layer.mask = gradient
This is what I have, and this is what I want as a result:
UPDATE:
Found the solution here.
You can do something like this:
var gradient = CAGradientLayer()
gradient.frame = imageView.bounds
gradient.colors = [UIColor.blue.cgColor, UIColor.purple.cgColor]
imageView.layer.insertSublayer(gradient, at: 0)
I got this answer. Add extension of UIImage and just pass colours list to apply gradient.
import UIKit
extension UIImage {
func tintedWithLinearGradientColors(colorsArr: [CGColor]) -> UIImage {
UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale);
guard let context = UIGraphicsGetCurrentContext() else {
return UIImage()
}
context.translateBy(x: 0, y: self.size.height)
context.scaleBy(x: 1, y: -1)
context.setBlendMode(.normal)
let rect = CGRect.init(x: 0, y: 0, width: size.width, height: size.height)
// Create gradient
let colors = colorsArr as CFArray
let space = CGColorSpaceCreateDeviceRGB()
let gradient = CGGradient(colorsSpace: space, colors: colors, locations: nil)
// Apply gradient
context.clip(to: rect, mask: self.cgImage!)
context.drawLinearGradient(gradient!, start: CGPoint(x: 0, y: 0), end: CGPoint(x: 0, y: self.size.height), options: .drawsAfterEndLocation)
let gradientImage = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
return gradientImage!
}
}

Resources