在 UIView 的 UIBezierPath 中为 startAngle 设置动画
Animate startAngle in UIBezierPath in UIView
我有一个 UIView 子类,它在其框架内绘制了一条弧线。绘制方法如下所示:
override func draw(_ rect: CGRect) {
let clockwise = true
let center: CGPoint = CGPoint(x: rect.midX, y: rect.midY)
let radius: CGFloat = rect.width / 2
self.trackWidth = min(max(trackWidth, 1), radius)
arc = UIBezierPath(arcCenter: center,
radius: radius - (trackWidth / 2),
startAngle: startAngle!,
endAngle: endAngle!,
clockwise: clockwise)
arc!.lineWidth = trackWidth
arc!.lineCapStyle = .round
self.color.setStroke()
arc!.stroke()
return
}
此代码是从另一个 SO'flow post 中提取的,但它工作正常,我正在使用它在界面中绘制静态弧。
我的问题是,如何为弧线制作动画,特别是 UIBezierPath 的 startAngle?到目前为止,我收集到这不能用常规的 UIView 动画来完成,所以 CABasicAnimation 似乎是首选。但是我不知道如何在这样的代码块中指定要设置动画的 属性:
func animateArc() {
CATransaction.begin()
var arc = arcs.first!
DemoView.animate(withDuration: 2.0) {
arc.layoutIfNeeded()
}
let animation = CABasicAnimation(keyPath: "startAngle")
animation.fromValue = 0
animation.toValue = DemoView.radianizer(40)
animation.autoreverses = false
animation.isRemovedOnCompletion = false
arc.layer.add(animation, forKey: "startAngle")
CATransaction.commit()
}
感谢收到的任何帮助。
您可以使用 layer-based 方法,而不是在 draw
中绘制路径。添加 CAShapeLayer
作为视图的子层。
let arcLayer = CAShapeLayer()
arcLayer.path = yourFullArc
arcLayer.strokeColor = self.color.cgColor
arcLayer.fillColor = UIColor.clear.cgColor
arcLayer.lineWidth = trackWidth
arcLayer.lineCap = .round
self.layer.addSublayer(arcLayer)
然后这个子层的 strokeStart
可以被动画化,这有点像动画化开始角度。 strokeStart
和 strokeEnd
的取值范围从 0 到 1,它们的基本意思是“你想抚摸线条的哪一部分”。现在您可以将“从”和“到”值 0 和 40 转换为 strokeStart
.
的值
然后可以像这样对图层进行动画处理:
// calculating values for strokeStart
let angleRange = endAngle! - startAngle!
let from = startAngle! / angleRange
let to = (startAngle! + DemoView.radianizer(40)) / angleRange
let animation = CABasicAnimation(keyPath: "strokeStart")
animation.fromValue = from
animation.toValue = to
animation.autoreverses = false
animation.isRemovedOnCompletion = false
arcLayer.add(animation, forKey: "someAnimation")
我有一个 UIView 子类,它在其框架内绘制了一条弧线。绘制方法如下所示:
override func draw(_ rect: CGRect) {
let clockwise = true
let center: CGPoint = CGPoint(x: rect.midX, y: rect.midY)
let radius: CGFloat = rect.width / 2
self.trackWidth = min(max(trackWidth, 1), radius)
arc = UIBezierPath(arcCenter: center,
radius: radius - (trackWidth / 2),
startAngle: startAngle!,
endAngle: endAngle!,
clockwise: clockwise)
arc!.lineWidth = trackWidth
arc!.lineCapStyle = .round
self.color.setStroke()
arc!.stroke()
return
}
此代码是从另一个 SO'flow post 中提取的,但它工作正常,我正在使用它在界面中绘制静态弧。
我的问题是,如何为弧线制作动画,特别是 UIBezierPath 的 startAngle?到目前为止,我收集到这不能用常规的 UIView 动画来完成,所以 CABasicAnimation 似乎是首选。但是我不知道如何在这样的代码块中指定要设置动画的 属性:
func animateArc() {
CATransaction.begin()
var arc = arcs.first!
DemoView.animate(withDuration: 2.0) {
arc.layoutIfNeeded()
}
let animation = CABasicAnimation(keyPath: "startAngle")
animation.fromValue = 0
animation.toValue = DemoView.radianizer(40)
animation.autoreverses = false
animation.isRemovedOnCompletion = false
arc.layer.add(animation, forKey: "startAngle")
CATransaction.commit()
}
感谢收到的任何帮助。
您可以使用 layer-based 方法,而不是在 draw
中绘制路径。添加 CAShapeLayer
作为视图的子层。
let arcLayer = CAShapeLayer()
arcLayer.path = yourFullArc
arcLayer.strokeColor = self.color.cgColor
arcLayer.fillColor = UIColor.clear.cgColor
arcLayer.lineWidth = trackWidth
arcLayer.lineCap = .round
self.layer.addSublayer(arcLayer)
然后这个子层的 strokeStart
可以被动画化,这有点像动画化开始角度。 strokeStart
和 strokeEnd
的取值范围从 0 到 1,它们的基本意思是“你想抚摸线条的哪一部分”。现在您可以将“从”和“到”值 0 和 40 转换为 strokeStart
.
然后可以像这样对图层进行动画处理:
// calculating values for strokeStart
let angleRange = endAngle! - startAngle!
let from = startAngle! / angleRange
let to = (startAngle! + DemoView.radianizer(40)) / angleRange
let animation = CABasicAnimation(keyPath: "strokeStart")
animation.fromValue = from
animation.toValue = to
animation.autoreverses = false
animation.isRemovedOnCompletion = false
arcLayer.add(animation, forKey: "someAnimation")