如何绘制另一层六边形 UIBezier Path 并相应地设置动画

问题描述

我正在寻找一种方法添加另一层六边形贝塞尔路径,如下所示。

enter image description here

我已经能够使用贝塞尔路径创建六边形并相应地设置动画,但我正在尝试添加一个灰色的贝塞尔路径层。我尝试添加多个贝塞尔曲线路径,但它不起作用。

这是我实现的输出

enter image description here

这是我的 LoaderView

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

这是动画的一帧的样子:

enter image description here

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...