代码之家  ›  专栏  ›  技术社区  ›  Jens

在特定点更改动画uibezierPath的颜色

  •  1
  • Jens  · 技术社区  · 6 年前

    我正在尝试使用 CAShapeLayer 和动画 UIBezierPath . 这个很好,但是我想让圆圈改变它 strokeColor 一旦动画达到某个值。

    例如:一旦画出75%的圆,我想切换 条纹颜色 UIColor.black.cgColor UIColor.red.cgColor .

    我的循环和“进度”动画代码如下:

    let circleLayer = CAShapeLayer()
    
    // set initial strokeColor:
    circleLayer.strokeColor = UIColor.black.cgColor
    circleLayer.path = UIBezierPath([...]).cgPath
    
    // animate the circle:
    let animation = CABasicAnimation()
    animation.keyPath = #keyPath(CAShapeLayer.strokeEnd)
    animation.fromValue = 0.0
    animation.toValue = 1
    animation.duration = 10
    animation.isAdditive = true
    animation.fillMode = .forwards
    circleLayer.add(animation, forKey: "strokeEnd")
    

    我知道这也可以创造一个 CABasicAnimation 对于 条纹颜色 并设置 fromValue toValue UIColors 为了得到 条纹颜色 慢慢改变。但这就像是一个随时间的过渡,而这并不是我想要的。

    更新1:

    根据米哈弗雷图的回答,我能够解决我的问题。为了将来参考,我想添加一个最小值 斯威夫特4 代码示例:

    // Create the layer with the circle path (UIBezierPath)
    let circlePathLayer = CAShapeLayer()
    circlePathLayer.path = UIBezierPath([...]).cgPath
    circlePathLayer.strokeEnd = 0.0
    circlePathLayer.strokeColor = UIColor.black.cgColor
    circlePathLayer.fillColor = UIColor.clear.cgColor
    self.layer.addSublayer(circlePathLayer)
    
    // Create animation to animate the progress (circle slowly draws)
    let progressAnimation = CABasicAnimation()
    progressAnimation.keyPath = #keyPath(CAShapeLayer.strokeEnd)
    progressAnimation.fromValue = 0.0
    progressAnimation.toValue = 1
    
    // Create animation to change the color
    let colorAnimation = CABasicAnimation()
    colorAnimation.keyPath = #keyPath(CAShapeLayer.strokeColor)
    colorAnimation.fromValue = UIColor.black.cgColor
    colorAnimation.toValue = UIColor.red.cgColor
    colorAnimation.beginTime = 3.75 // Since your total animation is 10s long, 75% is 7.5s - play with this if you need something else
    colorAnimation.duration = 0.001 // make this really small - this way you "hide" the transition
    colorAnimation.fillMode = .forwards
    
    // Group animations together
    let progressAndColorAnimation = CAAnimationGroup()
    progressAndColorAnimation.animations = [progressAnimation, colorAnimation]
    progressAndColorAnimation.duration = 5
    
    // Add animations to the layer
    circlePathLayer.add(progressAndColorAnimation, forKey: "strokeEndAndColor")
    
    1 回复  |  直到 6 年前
        1
  •  2
  •   Mihai Fratu    6 年前

    如果我正确理解了你的问题,这应该是你想要的。请牢记,它根本没有经过测试:

    let circleLayer = CAShapeLayer()
    
    // set initial strokeColor:
    circleLayer.strokeColor = UIColor.black.cgColor
    circleLayer.path = UIBezierPath([...]).cgPath
    
    // animate the circle:
    let animation = CABasicAnimation()
    animation.keyPath = #keyPath(CAShapeLayer.strokeEnd)
    animation.fromValue = 0.0
    animation.toValue = 1
    animation.beginTime = 0 // Being part of an animation group this is relative to the animation group start time
    animation.duration = 10
    animation.isAdditive = true
    animation.fillMode = .forwards
    
    // animate the circle color:
    let colorAnimation = CABasicAnimation()
    colorAnimation.keyPath = #keyPath(CAShapeLayer.strokeColor)
    colorAnimation.fromValue = UIColor.black.cgColor
    colorAnimation.toValue = UIColor.black.red
    colorAnimation.beginTime = 7.5 // Since your total animation is 10s long, 75% is 7.5s - play with this if you need something else
    colorAnimation.duration = 0.0001 // make this really small - this way you "hide" the transition
    colorAnimation.isAdditive = true
    colorAnimation.fillMode = .forwards
    
    let sizeAndColorAnimation = CAAnimationGroup()
    sizeAndColorAnimation.animations = [animation, colorAnimation]
    sizeAndColorAnimation.duration = 10
    
    circleLayer.add(sizeAndColorAnimation, forKey: "strokeEndAndColor")