Swift中的径向渐变背景

时间:2015-08-06 10:51:28

标签: ios swift

我一直试图产生一个基本的径向渐变背景,但没有成功。我设法得到一个线性渐变工作,如下面的代码所示,但我不知道如何使其不同的颜色径向 - 如下图所示。任何帮助将不胜感激。 :)

override func viewDidLoad() {
    super.viewDidLoad()

    //A linear Gradient Consists of two colours: top colour and bottom colour
    let topColor = UIColor(red: 15.0/255.0, green: 118.0/255.0, blue: 128.0/255.0, alpha: 1.0)
    let bottomColor = UIColor(red: 84.0/255.0, green: 187.0/255.0, blue: 187.0/255.0, alpha: 1.0)

    //Add the top and bottom colours to an array and setup the location of those two.
    let gradientColors: [CGColor] = [topColor.CGColor, bottomColor.CGColor]
    let gradientLocations: [CGFloat] = [0.0, 1.0]

    //Create a Gradient CA layer
    let gradientLayer: CAGradientLayer = CAGradientLayer()
    gradientLayer.colors = gradientColors
    gradientLayer.locations = gradientLocations

    gradientLayer.frame = self.view.bounds
    self.view.layer.insertSublayer(gradientLayer, atIndex: 0)
}

enter image description here

enter image description here

6 个答案:

答案 0 :(得分:22)

看看我的RadialGradientLayer实现,并随意修改它

class RadialGradientLayer: CALayer {

   override init(){

        super.init()

        needsDisplayOnBoundsChange = true
    }

     init(center:CGPoint,radius:CGFloat,colors:[CGColor]){

        self.center = center
        self.radius = radius
        self.colors = colors

        super.init()

    }

    required init(coder aDecoder: NSCoder) {

        super.init()

    }

    var center:CGPoint = CGPointMake(50,50)
    var radius:CGFloat = 20
    var colors:[CGColor] = [UIColor(red: 251/255, green: 237/255, blue: 33/255, alpha: 1.0).CGColor , UIColor(red: 251/255, green: 179/255, blue: 108/255, alpha: 1.0).CGColor]

    override func drawInContext(ctx: CGContext!) {

        CGContextSaveGState(ctx)

        var colorSpace = CGColorSpaceCreateDeviceRGB()

        var locations:[CGFloat] = [0.0, 1.0]

        var gradient = CGGradientCreateWithColors(colorSpace, colors, [0.0,1.0])

        var startPoint = CGPointMake(0, self.bounds.height)
        var endPoint = CGPointMake(self.bounds.width, self.bounds.height)

        CGContextDrawRadialGradient(ctx, gradient, center, 0.0, center, radius, 0)

    }

}

在我的情况下,我只需要两种颜色,如果你需要更多颜色,你需要修改location中声明的drawInContext数组。在从这个类创建对象后,不要忘记调用它setNeedsDisplay()否则它将无法工作。有时我需要不同的大小渐变,这就是为什么你必须在初始化器中传递radius参数和渐变的中心点

答案 1 :(得分:19)

如果您只是在寻找UIView径向渐变背景,那么这是Swift 3中的一个实现:

class RadialGradientLayer: CALayer {

    var center: CGPoint {
        return CGPoint(x: bounds.width/2, y: bounds.height/2)
    }

    var radius: CGFloat {
        return (bounds.width + bounds.height)/2
    }

    var colors: [UIColor] = [UIColor.black, UIColor.lightGray] {
        didSet {
            setNeedsDisplay()
        }
    }

    var cgColors: [CGColor] {
        return colors.map({ (color) -> CGColor in
            return color.cgColor
        })
    }

    override init() {
        super.init()
        needsDisplayOnBoundsChange = true
    }

    required init(coder aDecoder: NSCoder) {
        super.init()
    }

    override func draw(in ctx: CGContext) {
        ctx.saveGState()
        let colorSpace = CGColorSpaceCreateDeviceRGB()
        let locations: [CGFloat] = [0.0, 1.0]
        guard let gradient = CGGradient(colorsSpace: colorSpace, colors: cgColors as CFArray, locations: locations) else {
            return
        }
        ctx.drawRadialGradient(gradient, startCenter: center, startRadius: 0.0, endCenter: center, endRadius: radius, options: CGGradientDrawingOptions(rawValue: 0))
    }

}



class RadialGradientView: UIView {

    private let gradientLayer = RadialGradientLayer()

    var colors: [UIColor] {
        get {
            return gradientLayer.colors
        }
        set {
            gradientLayer.colors = newValue
        }
    }

    override func layoutSubviews() {
        super.layoutSubviews()
        if gradientLayer.superlayer == nil {
            layer.insertSublayer(gradientLayer, at: 0)
        }
        gradientLayer.frame = bounds
    }

}

答案 2 :(得分:17)

2020-现在非常容易做到这一点:

class GlowBall: UIView {
    private lazy var pulse: CAGradientLayer = {
        let l = CAGradientLayer()
        l.type = .radial
        l.colors = [ UIColor.red.cgColor,
            UIColor.yellow.cgColor,
            UIColor.green.cgColor,
            UIColor.blue.cgColor]
        l.locations = [ 0, 0.3, 0.7, 1 ]
        l.startPoint = CGPoint(x: 0.5, y: 0.5)
        l.endPoint = CGPoint(x: 1, y: 1)
        layer.addSublayer(l)
        return l
    }()

    override func layoutSubviews() {
        super.layoutSubviews()
        pulse.frame = bounds
        pulse.cornerRadius = bounds.width / 2.0
    }

}
    

enter image description here

关键行是:

l.colors = [ UIColor.red.cgColor,
                UIColor.yellow.cgColor,
                UIColor.green.cgColor,
                UIColor.blue.cgColor]
l.locations = [ 0, 0.3, 0.7, 1 ]
    

请注意,您可以根据需要更改“拉伸” ...

l.locations = [ 0, 0.1, 0.2, 1 ]
    
    

enter image description here

使用任何喜欢的颜色

l.colors = [ UIColor.systemBlue.cgColor,
                    UIColor.systemPink.cgColor,
                    UIColor.systemBlue.cgColor,
                    UIColor.systemPink.cgColor,
                    UIColor.systemBlue.cgColor,
                    UIColor.systemPink.cgColor,
                    UIColor.systemBlue.cgColor,
                    UIColor.systemPink.cgColor]
                l.locations = [ 0,0.1,0.2,0.3,0.4,0.5,0.6,1 ]
    

enter image description here

现在真的很容易。

非常有用的把戏:

说想要黄色,并在蓝带处设置为0.6:

l.colors = [ UIColor.yellow.cgColor,
                    UIColor.blue.cgColor,
                    UIColor.yellow.cgColor]
                l.locations = [ 0, 0.6, 1 ]
    

那很好。

    # yellow...
    # blue...
    # yellow...
    

但是通常您这样做:

    # yellow...
    # yellow...
    # blue...
    # yellow...
    # yellow...
    

请注意,有两种黄色...

l.colors = [ UIColor.yellow.cgColor,
 UIColor.yellow.cgColor,
 UIColor.blue.cgColor,
 UIColor.yellow.cgColor,
  UIColor.yellow.cgColor]
    

现在,您可以控制“宽度” :蓝色带是

在此示例中:蓝带将窄而锐利

l.locations = [ 0, 0.58, 0.6, 0.68, 1 ]
    

在此示例中,蓝色带将柔和

l.locations = [ 0, 0.5, 0.6, 0.7, 1 ]
    

这真的是控制渐变并获得所需外观的秘诀。

答案 3 :(得分:4)

@IBDesignable class RadialGradientView: UIView {

    @IBInspectable var outsideColor: UIColor = UIColor.red
    @IBInspectable var insideColor: UIColor = UIColor.green

    override func draw(_ rect: CGRect) {
        let colors = [insideColor.cgColor, outsideColor.cgColor] as CFArray
        let endRadius = sqrt(pow(frame.width/2, 2) + pow(frame.height/2, 2))
        let center = CGPoint(x: bounds.size.width / 2, y: bounds.size.height / 2)
        let gradient = CGGradient(colorsSpace: nil, colors: colors, locations: nil)
        let context = UIGraphicsGetCurrentContext()

        context?.drawRadialGradient(gradient!, startCenter: center, startRadius: 0.0, endCenter: center, endRadius: endRadius, options: CGGradientDrawingOptions.drawsBeforeStartLocation)
    }
}

请参阅完整的答案here

答案 4 :(得分:1)

Here is a link for a really great resource with a range of gradients and blend factors included with some animations. Works in SpriteKit too. ;)

enter image description here

答案 5 :(得分:0)

一种功能稍有不同的方法,该方法将父视图,颜色和位置作为输入。该函数返回添加了图层的子视图。这样可以灵活地隐藏/显示/删除子视图。

enter image description here

override func viewDidLoad() {
    super.viewDidLoad()
    //squareView is my parent view I am going to add gradient view to it
    squareView.backgroundColor = UIColor.black
    //Add CG colors
    let colours = [UIColor.red.cgColor,UIColor.green.cgColor,UIColor.clear.cgColor]
    //Add location with same count as colors, these describe contribution in gradient from center 0 to end 1
    let locations:[NSNumber] = [0,0.6,0.8]
    //Use gradientView reference to show/hide, remove/re-add from view
    let gradientView = self.addGradientViewTo(parentView: self.squareView, colors:colours,locations: locations)
}

func addGradientViewTo (parentView:UIView,colors:[CGColor],locations:[NSNumber]) -> UIView  {
    //Create customGradientView with exact dimension of parent, add it with centering with parent
    let customGradientView = UIView()
    customGradientView.backgroundColor = UIColor.clear
    customGradientView.frame = parentView.bounds
    parentView.addSubview(customGradientView)
    customGradientView.centerXAnchor.constraint(equalTo: parentView.centerXAnchor).isActive = true
    customGradientView.centerYAnchor.constraint(equalTo: parentView.centerYAnchor).isActive = true
    parentView.clipsToBounds = true

    //Create layer add it to customGradientView
    let gradientLayer = CAGradientLayer()
    gradientLayer.type = .radial //Circular
    gradientLayer.opacity = 0.8
    gradientLayer.colors = colors
    gradientLayer.locations = locations
    gradientLayer.frame = customGradientView.bounds
    
    //Set start point as center and radius as 1, co-ordinate system maps 0 to 1, 0,0 top left, bottom right 1,1
    gradientLayer.startPoint = CGPoint(x: 0.5, y: 0.5)
    let radius = 1.0
    gradientLayer.endPoint = CGPoint(x: radius, y: radius)
          
    //Add layer at top to make sure its visible
    let layerCount:UInt32 = UInt32(customGradientView.layer.sublayers?.count ?? 0)
    customGradientView.layer.insertSublayer(gradientLayer, at: layerCount)
    customGradientView.layoutIfNeeded()
    
    //Use reference to show/hide add/remove gradient view
    return customGradientView
}
相关问题