将线性渐变应用于线段(UIBezierPath)

时间:2017-03-15 16:47:06

标签: ios swift linear-gradients cagradientlayer radial-gradients

我引用previous problem(已解决),因为它提出了一个新问题:

我现在有了线性渐变但我无法从中心开始并在饼图区段(UIBezierPath)的另一侧结束。

func arc(myRadius: CGFloat, myStartAngle: CGFloat, myEndAngle: CGFloat) {

    context?.saveGState()

    var finalRadius: CGFloat = myRadius
    (...)

    let myBezier = UIBezierPath()
    myBezier.move(to: center)
    myBezier.addArc(withCenter: center, radius: finalRadius, startAngle: myStartAngle, endAngle: myEndAngle, clockwise: false)
    myBezier.close()
    myColor.setFill()
    myBezier.fill()
    context?.addPath(myBezier.cgPath)

    context?.clip()

    let shape = CAShapeLayer()
    shape.frame = self.bounds
    shape.path = myBezier.cgPath
    shape.strokeColor = UIColor.black.cgColor
    shape.lineWidth = 0.5
    shape.fillColor = nil

    let grad = CAGradientLayer()
    grad.frame = self.bounds // I tried here myBezier.bounds without any success (I don't see any gradient)
    grad.colors = [UIColor.brown.cgColor, UIColor.yellow.cgColor]
    grad.locations = [0.0, 1.0]

    // StartPoint and endPoint not showing what I want...
    grad.startPoint = center
    grad.endPoint = CGPoint(x: centerX + cos(myStartAngle), y: centerY + sin(myStartAngle))

    let mask = CAShapeLayer()
    mask.frame = self.bounds
    mask.path = myBezier.cgPath
    mask.fillColor = UIColor.black.cgColor
    grad.mask = mask

    self.layer.addSublayer(grad)
    self.layer.addSublayer(shape)
    }

    context?.restoreGState()
}

也许我应该从中心开始使用径向渐变并且我不关心任何片段,我只是将它应用于面具上它应该可以工作。但我认为应该有一种方法将线性渐变应用于视图中的特定帧,并将start和endPoint设置为此帧。问题是它在尝试插入角度时没有按照我想要的方式...

这就是我得到的:

enter image description here

有没有人知道我应该如何更改我的CAGradientLayer以获得从中心开始到弧形(对面)结束的线性渐变?

1 个答案:

答案 0 :(得分:0)

grad.startPointgrad.endPoint定义为:

  

该点在单位坐标空间中定义,然后在绘制时映射到图层的边界矩形。

你想:

grad.startPoint = CGPoint(x: center.x/self.bounds.width, y: center.y/self.bounds.height)
grad.endPoint = CGPoint(x: (center.x+(cos(myStartAngle)* finalRadius))/self.bounds.width, y: (center.y+(sin(myStartAngle)* finalRadius))/self.bounds.height)

BTW:一个非常好的调试方法是注释grad.mask = mask,这样你就可以看到整个渐变,看看开始/结束是如何工作的。

如果您仍然无法使用它,那么这是游乐场的代码

//: Playground - noun: a place where people can play

import UIKit
import QuartzCore

class Arc: UIView {
    public override init(frame: CGRect) {
        super.init(frame:frame)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func draw(_ rect: CGRect) {
        if let context = UIGraphicsGetCurrentContext() {
            let myBezier = UIBezierPath()
            let center = CGPoint(x:80, y:140)
            let r: CGFloat = 450
            myBezier.move(to: center)
            myBezier.addArc(withCenter: center, radius: r, startAngle: 0.1, endAngle: 0.5, clockwise: true)
            myBezier.close()
            UIColor.blue.setFill()
            myBezier.fill()
            context.addPath(myBezier.cgPath)
            context.clip()
            let shape = CAShapeLayer()
            shape.frame = self.bounds
            shape.path = myBezier.cgPath
            shape.strokeColor = UIColor.red.cgColor
            shape.lineWidth = 0.5
            shape.fillColor = nil

            let grad = CAGradientLayer()
            grad.frame = self.bounds // I tried here myBezier.bounds without any success (I don't see any gradient)
            grad.colors = [UIColor.black.cgColor, UIColor.white.cgColor]

            grad.startPoint = CGPoint(x: center.x/self.bounds.width, y: center.y/self.bounds.height)
            grad.endPoint = CGPoint(x: (center.x+(cos(0.1)*r))/self.bounds.width, y: (center.y+(sin(0.1)*r))/self.bounds.height)

            let mask = CAShapeLayer()
            mask.frame = self.bounds
            mask.path = myBezier.cgPath
            mask.fillColor = UIColor.black.cgColor
            grad.mask = mask

            self.layer.addSublayer(grad)
            self.layer.addSublayer(shape)
        }
    }
}

let v = Arc(frame: CGRect(x: 0, y: 0, width: 600, height: 600))
v.backgroundColor = .green