【问题标题】:Swift 3: CAShapeLayer mask not animating for pie chart animationSwift 3:CAShapeLayer 蒙版没有为饼图动画制作动画
【发布时间】:2017-12-01 05:19:52
【问题描述】:

我的代码可以在给定任意输入数据的情况下成功创建饼图。它会生成一个如下所示的饼图:

我想要什么:

我希望创建一个动画,按顺序绘制饼图的这些部分。也就是说,我希望执行饼图的“时钟滑动”动画。屏幕应该从黑色开始,然后逐渐填充以生成上面的饼图图像。

问题:

我正在尝试为每个饼图块创建图层蒙版并为图层蒙版设置动画,以便饼图块填充动画。但是,当我实现图层蒙版时,它没有动画并且屏幕保持黑色。

代码:

class GraphView: UIView {
    // Array of colors for graph display
    var colors: [CGColor] = [UIColor.orange.cgColor, UIColor.cyan.cgColor, UIColor.green.cgColor, UIColor.blue.cgColor]

    override func draw(_ rect: CGRect) {
        drawPieChart()
    }

    func drawPieChart() {
        // Get data from file, yields array of numbers that sum to 100
        let data: [String] = getData(from: "pie_chart")

        // Create the pie chart
        let pieCenter: CGPoint = CGPoint(x: frame.width / 2, y: frame.height / 2)
        let radius = frame.width / 3
        let rad = 2 * Double.pi
        var lastEnd: Double = 0
        var start: Double = 0

        for i in 0...data.count - 1 {
            let size = Double(data[i])! / 100
            let end: Double = start + (size * rad)

            // Create the main layer
            let path = UIBezierPath()
            path.move(to: pieCenter)
            path.addArc(withCenter: pieCenter, radius: radius, startAngle: CGFloat(start), endAngle: CGFloat(end), clockwise: true)

            let shapeLayer = CAShapeLayer()
            shapeLayer.path = path.cgPath
            shapeLayer.fillColor = colors[i] 

            // Create the mask
            let maskPath = CGMutablePath()
            maskPath.move(to: pieCenter)
            maskPath.addArc(center: pieCenter, radius: radius, startAngle: CGFloat(start), endAngle: CGFloat(end), clockwise: true)

            let shapeLayerMask = CAShapeLayer()
            shapeLayerMask.path = maskPath
            shapeLayerMask.fillColor = colors[i]
            shapeLayerMask.lineWidth = radius
            shapeLayerMask.strokeStart = 0
            shapeLayerMask.strokeEnd = 1

            // Set the mask
            shapeLayer.mask = shapeLayerMask
            shapeLayer.mask!.frame = shapeLayer.bounds

            // Add the masked layer to the main layer
            self.layer.addSublayer(shapeLayer)

            // Animate the mask
            DispatchQueue.main.asyncAfter(deadline: .now() + Double(i)) {
                let animation = CABasicAnimation(keyPath: "strokeEnd")
                animation.fromValue = shapeLayerMask.strokeStart
                animation.toValue = shapeLayerMask.strokeEnd
                animation.duration = 4
                animation.timingFunction = CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear)
                animation.isRemovedOnCompletion = false
                animation.autoreverses = false

                shapeLayerMask.add(animation, forKey: nil)
            }

            start = end
        }
    }
}

同样,这段代码只是产生一个空白屏幕。如果注释掉遮罩相关代码并添加shapeLayer作为子视图,您将看到未动画的饼图。

我做错了什么,如何让我的饼图动画化?

【问题讨论】:

    标签: ios swift core-graphics core-animation


    【解决方案1】:

    子层必须添加到父层才能被屏蔽:

    // Code above this line adds the pie chart slices to the parentLayer
    for layer in parentLayer.sublayers! {
        // Code in this block creates and animates a mask for each layer
    }
    // Add the parent layer to the highest parent view/layer
    

    这就是它的全部内容。您必须确保饼图切片和子图层之间存在一一对应。 这样做的原因是因为您不能使用图层蒙版的一个实例来屏蔽多个视图/图层。执行此操作时,图层蒙版将成为您尝试蒙版的图层的Layer Hierarchy 的一部分。必须在遮罩和要遮罩的图层之间建立父子关系才能使其正常工作。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-01-02
      • 2013-08-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-11-22
      • 1970-01-01
      相关资源
      最近更新 更多