我引用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设置为此帧。问题是它在尝试插入角度时没有按照我想要的方式...
这就是我得到的:
有没有人知道我应该如何更改我的CAGradientLayer
以获得从中心开始到弧形(对面)结束的线性渐变?
答案 0 :(得分:0)
grad.startPoint
和grad.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