I have UIView for drawing.
Can i change stroke line from default
CGContextSetStrokeColorWithColor(context, UIColor.blackColor().CGColor)
to https://www.img.in.th/image/79xF
or http://catheria.com/wp-content/uploads/2015/10/StrokeLinear.png
below is code draw radius gradient
UIGraphicsBeginImageContextWithOptions(size, false, 0.0)
let ctx0 = UIGraphicsGetCurrentContext()
let colorSpace: CGColorSpaceRef = CGColorSpaceCreateDeviceRGB()!
let locations: [CGFloat] = [0.0, 0.4, 1.0]
let arrColor = [UIColor.blackColor().CGColor,UIColor.blackColor().CGColor, UIColor.clearColor().CGColor]
let _gradient: CGGradientRef = CGGradientCreateWithColors(colorSpace, arrColor, locations)!
CGContextDrawRadialGradient(ctx0, _gradient, CGPoint(x: size.width/2, y: size.height/2), CGFloat(0), CGPoint(x: size.width/2, y: size.height/2), CGFloat(60), CGGradientDrawingOptions())
let _img0 = UIGraphicsGetImageFromCurrentImageContext()
UIGraphicsEndImageContext()
Related
I use this code to generate an UIImage from a gradient.
func buildGradientImage() -> UIImage? {
let gradientLayer = CAGradientLayer()
gradientLayer.frame = CGRect(x: 0, y: 0, width: 375, height: 667)
gradientLayer.type = .radial
gradientLayer.startPoint = CGPoint(x: 0.0, y: 0.0)
gradientLayer.endPoint = CGPoint(x: 1.2, y: 1.0)
gradientLayer.colors = [UIColor.red.cgColor, UIColor.green.cgColor]
var gradientImage:UIImage?
UIGraphicsBeginImageContext(gradientLayer.frame.size)
if let context = UIGraphicsGetCurrentContext() {
gradientLayer.render(in: context)
gradientImage = UIGraphicsGetImageFromCurrentImageContext()
}
UIGraphicsEndImageContext()
return gradientImage
}
For some reason the resulting image is different between iOS 12 and iOS 13-14.
Red seems to expand more on the iOS 12 gradient.
Someone know why there is this difference? Shouldn't the code generate the same gradient?
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()
}
Any idea on how to fill all the paths in here. What is currently happening is that I draw a rectangle path on my view then add small circles in between but it seems that if the circle and rectangle intersects, the white fill color is showing. What I would want is show still the gradient layer. Any help? My current code is below.
func addGradientLayer() {
let gradientLayer = CAGradientLayer()
gradientLayer.frame = bounds
let startColor = UIColor.create(withHexOrName: OurPayStatesViewUX.GradientColorStart)
let endColor = UIColor.create(withHexOrName: OurPayStatesViewUX.GradientColorEnd)
gradientLayer.colors = [startColor.CGColor, endColor.CGColor]
gradientLayer.startPoint = CGPoint(x: 0, y: 0)
gradientLayer.endPoint = CGPoint(x: 1, y: 0)
layer.insertSublayer(gradientLayer, atIndex: 0)
}
func createOverlay(view: UIView, circleLocations: [CGPoint]) {
maskLayer?.removeFromSuperlayer()
let radius: CGFloat = view.frame.height/2
let path = UIBezierPath(roundedRect: CGRect(x: 0, y: 0, width: view.bounds.size.width, height: view.bounds.size.height), cornerRadius: 0)
for i in circleLocations {
// Create a circle path in each of the state views
let circlePath = UIBezierPath(roundedRect: CGRect(x: i.x, y: i.y, width: 2 * radius, height: 2 * radius), cornerRadius: radius)
path.appendPath(circlePath)
}
let rect = createRectangle(startPointX: 0, endPointX: view.bounds.size.width)
path.appendPath(rect)
path.usesEvenOddFillRule = true
let fillLayer = CAShapeLayer()
fillLayer.path = path.CGPath
fillLayer.fillRule = kCAFillRuleEvenOdd
fillLayer.fillColor = backgroundColor?.CGColor ?? UIColor.whiteColor().CGColor
fillLayer.opacity = 1
maskLayer = fillLayer
layer.addSublayer(fillLayer)
}
func createRectangle(startPointX startPointX: CGFloat, endPointX: CGFloat) -> UIBezierPath {
let rectHeight: CGFloat = 6
let path = UIBezierPath(rect: CGRect(x: startPointX, y: frame.height/2 - rectHeight/2, width: endPointX - startPointX, height: rectHeight))
return path
}
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!
}
}
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)
}