【问题标题】:How do I set an endpoint for a CAKeyFrameAnimation?如何为 CAKeyFrameAnimation 设置端点?
【发布时间】:2021-10-06 15:24:58
【问题描述】:

我正在使用弧线作为进度条。

有一个跟踪层,进度指示器沿着它移动,我还有一个随着进度条移动的圆圈,以增加重点。进度条和圆圈都沿路径正确移动,但是当进度完成时,圆圈不会停在路径的尽头,而是跳回到进度路径的开头。

screen recording of behavior

代码:

class ViewController: UIViewController {
    
    let shapeLayer = CAShapeLayer()
    let trackLayer = CAShapeLayer()
    let dotLayer: CALayer = CALayer()
    let seconds = 10.0
    
    // MARK: - Properties
    private var progressBarView = UIView()
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        title = "Making Progress"
        view.backgroundColor = .systemTeal
        
        // determine the value of Center
        let center = view.center
        
        let circularPath = UIBezierPath(arcCenter: center, radius: 100, startAngle: 2.7, endAngle: 0.45, clockwise: true) // these values give us a complete circle
        
        trackLayer.path = circularPath.cgPath
        trackLayer.strokeColor = UIColor.lightGray.cgColor
        trackLayer.lineWidth = 10
        trackLayer.fillColor = UIColor.clear.cgColor
        trackLayer.lineCap = .round
        
        view.layer.addSublayer(trackLayer)
        
        shapeLayer.path = circularPath.cgPath
        
        shapeLayer.strokeColor = UIColor.red.cgColor
        shapeLayer.lineWidth = 10
        shapeLayer.strokeEnd = 0
        shapeLayer.fillColor = UIColor.clear.cgColor
        shapeLayer.lineCap = .round
        
        view.layer.addSublayer(shapeLayer)
        
        view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(handleTap )))
    }
    
    @objc private func handleTap() {
        print("Attempting to animate stroke")
        
        let basicAnimation = CABasicAnimation(keyPath: "strokeEnd")
        
        basicAnimation.toValue = 1
        
        basicAnimation.duration = seconds
        
        basicAnimation.fillMode = CAMediaTimingFillMode.forwards
        basicAnimation.isRemovedOnCompletion = false
        
        shapeLayer.add(basicAnimation, forKey: "anyKeyWillDo")
        
        // circle image
        let circleNobImage = UIImage(named: "whiteCircle.png")!
        
        dotLayer.contents = circleNobImage.cgImage
        dotLayer.bounds = CGRect(x: 0.0, y: 0.0, width: circleNobImage.size.width, height: circleNobImage.size.height)
        
        view.layer.addSublayer(dotLayer)
        
        dotLayer.position = CGPoint(x: 105, y: 460)
        
        dotLayer.opacity = 1
        
        dotAnimation()
    }
    
    func dotAnimation() {
        let dotAnimation = CAKeyframeAnimation(keyPath: "position")
        dotAnimation.path = trackLayer.path
        dotAnimation.calculationMode = .paced
        
        let dotAnimationGroup = CAAnimationGroup()
        dotAnimationGroup.duration = seconds
        
        dotAnimation.autoreverses = false
        dotAnimationGroup.animations = [dotAnimation]
        dotLayer.add(dotAnimationGroup, forKey: nil)
    }
}

我需要用进度条让圆圈停在弧的末端。这是怎么做到的?

【问题讨论】:

    标签: swift core-animation cakeyframeanimation


    【解决方案1】:

    同时设置dotAnimationGroup.fillModedotAnimationGroup.isRemovedOnCompletion

    dotAnimationGroup.fillMode = .forwards
    dotAnimationGroup.isRemovedOnCompletion = false
    

    【讨论】:

    • 第二行就大不一样了。非常感谢!
    • Raja 描述的内容可行,但不是一个很好的解决方案。这会导致动画的“表示层”在动画完成后仍然存在。底层实际上并未移动。通常最好在添加动画后立即将图层设置为最终状态。这种变化被“飞行中的”动画隐藏,一旦动画完成并且表示层被隐藏,就会显示出来。
    • @DuncanC 如果您愿意,我将不胜感激。
    猜你喜欢
    • 1970-01-01
    • 2021-12-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-10
    • 2016-03-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多