我正在使用UIBezierPath创建以下形状,然后使用CAShapeLayer如下绘制它。
然后,我可以将CAShapeLayer fillColor属性从更改shapeLayer.fillColor = UIColor.clear.cgColor
为shapeLayer.fillColor = UIColor.blue.cgColor
并获得以下形状。
这是代码:
import UIKit
class ViewController: UIViewController {
var line = [CGPoint]()
let bezierPath: UIBezierPath = UIBezierPath()
override func viewDidLoad() {
super.viewDidLoad()
view.backgroundColor = .white
let point1 = CGPoint(x: 100, y: 100)
let point2 = CGPoint(x: 400, y: 100)
line.append(point1)
line.append(point2)
addCircle(toRight: false)
addLine()
addCircle(toRight: true)
let shapeLayer = CAShapeLayer()
shapeLayer.path = bezierPath.cgPath
shapeLayer.strokeColor = UIColor.blue.cgColor
shapeLayer.fillColor = UIColor.clear.cgColor
self.view.layer.addSublayer(shapeLayer)
}
func addLine() -> Void {
bezierPath.move(to: line.first!)
bezierPath.addLine(to: line.last!)
}
func addCircle(toRight: Bool) -> Void {
let angle = CGFloat( Double.pi / 180 )
let r = CGFloat(20.0)
let x0 = toRight ? line.first!.x : line.last!.x
let y0 = toRight ? line.first!.y : line.last!.y
let x1 = toRight ? line.last!.x : line.first!.x
let y1 = toRight ? line.last!.y : line.first!.y
let x = x1 - x0
let y = y1 - y0
let h = (x*x + y*y).squareRoot()
let x2 = x0 + (x * (h + r) / h)
let y2 = y0 + (y * (h + r) / h)
// Add the arc, starting at that same point
let point2 = CGPoint(x: x2, y: y2)
let pointZeroDeg = CGPoint(x: x2 + r, y: y2)
self.bezierPath.move(to: pointZeroDeg)
self.bezierPath.addArc(withCenter: point2, radius: r,
startAngle: 0*angle, endAngle: 360*angle,
clockwise: true)
self.bezierPath.close()
}
}
但是我真正想要的是跟随形状(填充左侧圆,不填充右侧圆)。
所以我的问题是,如何仅填充CAShapeLayer上的一部分形状?可能吗?有什么技巧可以实现这一目标吗?
PS:我可以通过创建3个不同的UIBezierPaths(分别用于leftCircle,line和rightCircle)并使用以下3个不同的CAShapeLayers进行绘制来实现此目的。
// left Circle
shapeLayer1.path = bezierPath1.cgPath
shapeLayer1.fillColor = UIColor.blue.cgColor
// line
shapeLayer2.path = bezierPath2.cgPath
// right Circle
shapeLayer3.path = bezierPath3.cgPath
shapeLayer3.fillColor = UIColor.clear.cgColor
self.view.layer.addSublayer(shapeLayer1)
self.view.layer.addSublayer(shapeLayer2)
self.view.layer.addSublayer(shapeLayer3)
But I prefer to achieve this with a single CAShapeLayer.
I think better approach is using of multiple shapes.
However you can make one-shape implementation by using evenOdd
rule of shape filling.
Just add an extra circle to the right circle in method addCircle
:
if toRight {
self.bezierPath.addArc(withCenter: point2, radius: r,
startAngle: 0*angle, endAngle: 2*360*angle,
clockwise: true)
} else {
self.bezierPath.addArc(withCenter: point2, radius: r,
startAngle: 0*angle, endAngle: 360*angle,
clockwise: true)
}
And set fillRule
to evenOdd
:
shapeLayer.fillColor = UIColor.blue.cgColor
shapeLayer.fillRule = .evenOdd
So you'll get that the left circle will have one circle of drawing and will be filled by evenOdd
rule. But right circle will have two circles of drawing and will be unfilled.
The evenOdd
rule (https://developer.apple.com/documentation/quartzcore/cashapelayerfillrule/1521843-evenodd):
指定奇偶缠绕规则。计算过路通道的总数。如果交叉点数为偶数,则该点位于路径之外。如果交叉点的数量为奇数,则该点在路径内,并且应填充包含该点的区域。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句