如何绘制另一层六边形 UIBezierPath 并相应地设置动画
How to draw another layer of hexagon UIBezier Path and animate accordingly
我正在寻找一种方法来添加另一层六边形贝塞尔曲线路径,如下所示。
我已经能够使用贝塞尔曲线路径创建六边形并相应地设置动画,但我正在尝试添加另一个贝塞尔曲线路径的灰色层。我尝试添加多个贝塞尔曲线路径,但它不起作用。
这是我实现的输出。
这是我的LoaderView
class
class LoaderView: UIView {
private let lineWidth : CGFloat = 5
internal var backgroundMask = CAShapeLayer()
override init(frame: CGRect) {
super.init(frame: frame)
setUpLayers()
createAnimation()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setUpLayers()
createAnimation()
}
func setUpLayers()
{
backgroundMask.lineWidth = lineWidth
backgroundMask.fillColor = nil
backgroundMask.strokeColor = UIColor.blue.cgColor
layer.mask = backgroundMask
layer.addSublayer(backgroundMask)
}
func createAnimation()
{
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.fromValue = 0
animation.duration = 1
animation.repeatCount = .infinity
backgroundMask.add(animation, forKey: "MyAnimation")
}
override func draw(_ rect: CGRect) {
let sides = 6
let rect = self.bounds
let path = UIBezierPath()
let cornerRadius : CGFloat = 10
let rotationOffset = CGFloat(.pi / 2.0)
let theta: CGFloat = CGFloat(2.0 * .pi) / CGFloat(sides) // How much to turn at every corner
let width = min(rect.size.width, rect.size.height) // Width of the square
let center = CGPoint(x: rect.origin.x + width / 2.0, y: rect.origin.y + width / 2.0)
// Radius of the circle that encircles the polygon
// Notice that the radius is adjusted for the corners, that way the largest outer
// dimension of the resulting shape is always exactly the width - linewidth
let radius = (width - lineWidth + cornerRadius - (cos(theta) * cornerRadius)) / 2.0
// Start drawing at a point, which by default is at the right hand edge
// but can be offset
var angle = CGFloat(rotationOffset)
let corner = CGPoint(x: center.x + (radius - cornerRadius) * cos(angle), y: center.y + (radius - cornerRadius) * sin(angle))
path.move(to: CGPoint(x: corner.x + cornerRadius * cos(angle + theta), y: corner.y + cornerRadius * sin(angle + theta)))
for _ in 0..<sides {
angle += theta
let corner = CGPoint(x: center.x + (radius - cornerRadius) * cos(angle), y: center.y + (radius - cornerRadius) * sin(angle))
let tip = CGPoint(x: center.x + radius * cos(angle), y: center.y + radius * sin(angle))
let start = CGPoint(x: corner.x + cornerRadius * cos(angle - theta), y: corner.y + cornerRadius * sin(angle - theta))
let end = CGPoint(x: corner.x + cornerRadius * cos(angle + theta), y: corner.y + cornerRadius * sin(angle + theta))
path.addLine(to: start)
path.addQuadCurve(to: end, controlPoint: tip)
}
path.close()
backgroundMask.path = path.cgPath
}}
要在蓝色动画路径下添加灰色六边形,可以再添加一个CAShapeLayer
:
var grayLayer = CAShapeLayer()
以类似于 backgroundMask
的方式进行设置:
grayLayer.lineWidth = lineWidth
grayLayer.fillColor = nil
grayLayer.strokeColor = UIColor.gray.cgColor
将其路径设置为与backgroundMask
:
相同的路径
backgroundMask.path = path.cgPath
grayLayer.path = path.cgPath
最后,在添加 backgroundMask
之前 添加灰色层 。这使它位于底部:
layer.addSublayer(grayLayer)
layer.addSublayer(backgroundMask)
另请注意,您的路径绘制代码不需要进入 draw
。它可以直接进入 init
.
动画的一帧如下所示:
我正在寻找一种方法来添加另一层六边形贝塞尔曲线路径,如下所示。
我已经能够使用贝塞尔曲线路径创建六边形并相应地设置动画,但我正在尝试添加另一个贝塞尔曲线路径的灰色层。我尝试添加多个贝塞尔曲线路径,但它不起作用。
这是我实现的输出。
这是我的LoaderView
class
class LoaderView: UIView {
private let lineWidth : CGFloat = 5
internal var backgroundMask = CAShapeLayer()
override init(frame: CGRect) {
super.init(frame: frame)
setUpLayers()
createAnimation()
}
required init?(coder: NSCoder) {
super.init(coder: coder)
setUpLayers()
createAnimation()
}
func setUpLayers()
{
backgroundMask.lineWidth = lineWidth
backgroundMask.fillColor = nil
backgroundMask.strokeColor = UIColor.blue.cgColor
layer.mask = backgroundMask
layer.addSublayer(backgroundMask)
}
func createAnimation()
{
let animation = CABasicAnimation(keyPath: "strokeEnd")
animation.fromValue = 0
animation.duration = 1
animation.repeatCount = .infinity
backgroundMask.add(animation, forKey: "MyAnimation")
}
override func draw(_ rect: CGRect) {
let sides = 6
let rect = self.bounds
let path = UIBezierPath()
let cornerRadius : CGFloat = 10
let rotationOffset = CGFloat(.pi / 2.0)
let theta: CGFloat = CGFloat(2.0 * .pi) / CGFloat(sides) // How much to turn at every corner
let width = min(rect.size.width, rect.size.height) // Width of the square
let center = CGPoint(x: rect.origin.x + width / 2.0, y: rect.origin.y + width / 2.0)
// Radius of the circle that encircles the polygon
// Notice that the radius is adjusted for the corners, that way the largest outer
// dimension of the resulting shape is always exactly the width - linewidth
let radius = (width - lineWidth + cornerRadius - (cos(theta) * cornerRadius)) / 2.0
// Start drawing at a point, which by default is at the right hand edge
// but can be offset
var angle = CGFloat(rotationOffset)
let corner = CGPoint(x: center.x + (radius - cornerRadius) * cos(angle), y: center.y + (radius - cornerRadius) * sin(angle))
path.move(to: CGPoint(x: corner.x + cornerRadius * cos(angle + theta), y: corner.y + cornerRadius * sin(angle + theta)))
for _ in 0..<sides {
angle += theta
let corner = CGPoint(x: center.x + (radius - cornerRadius) * cos(angle), y: center.y + (radius - cornerRadius) * sin(angle))
let tip = CGPoint(x: center.x + radius * cos(angle), y: center.y + radius * sin(angle))
let start = CGPoint(x: corner.x + cornerRadius * cos(angle - theta), y: corner.y + cornerRadius * sin(angle - theta))
let end = CGPoint(x: corner.x + cornerRadius * cos(angle + theta), y: corner.y + cornerRadius * sin(angle + theta))
path.addLine(to: start)
path.addQuadCurve(to: end, controlPoint: tip)
}
path.close()
backgroundMask.path = path.cgPath
}}
要在蓝色动画路径下添加灰色六边形,可以再添加一个CAShapeLayer
:
var grayLayer = CAShapeLayer()
以类似于 backgroundMask
的方式进行设置:
grayLayer.lineWidth = lineWidth
grayLayer.fillColor = nil
grayLayer.strokeColor = UIColor.gray.cgColor
将其路径设置为与backgroundMask
:
backgroundMask.path = path.cgPath
grayLayer.path = path.cgPath
最后,在添加 backgroundMask
之前 添加灰色层 。这使它位于底部:
layer.addSublayer(grayLayer)
layer.addSublayer(backgroundMask)
另请注意,您的路径绘制代码不需要进入 draw
。它可以直接进入 init
.
动画的一帧如下所示: