我想为划线阶段添加动画,但遇到了动画缺陷。如何解决这些缺陷以实现给定线宽的流畅连续动画?
我更新了代码但没有改变原来的问题;我只是添加了一个按钮来启动和停止动画。
import SwiftUI
struct ContentView: View {
let lineWidth: CGFloat = 90.0
var body: some View {
DashedCircleView(lineWidth: lineWidth)
}
}
struct DashedCircleView: View {
let lineWidth: CGFloat
@State private var phaseAnimation: Bool = Bool()
@State private var animation: Animation? = nil
var body: some View {
VStack {
Spacer()
Circle()
.strokeBorder(Color.red, style: StrokeStyle(
lineWidth: lineWidth,
dash: [2*lineWidth],
dashPhase: phaseAnimation ? 4*lineWidth : .zero))
.frame(width: 400, height: 400)
.animation(animation, value: phaseAnimation)
Spacer()
Button("run Animation") {
if (phaseAnimation) {
animation = Animation.interactiveSpring
phaseAnimation.toggle()
}
else {
animation = Animation.linear(duration: 1).repeatForever(autoreverses: false)
phaseAnimation.toggle()
}
}
}
.padding()
}
}
更新:工作代码:
import SwiftUI
struct ContentView: View {
var body: some View {
DashedCircleView(lineWidth: 30.0, dashCount: 10, size: 400.0)
}
}
struct DashedCircleView: View {
let lineWidth: CGFloat
let dashCount: Int
let size: CGFloat
@State private var phaseAnimation: Bool = Bool()
var body: some View {
VStack {
Spacer()
Circle()
.strokeBorder(Color.red, style: StrokeStyle(lineWidth: lineWidth,
dash: [(size - lineWidth) * CGFloat.pi / (CGFloat(dashCount)*2.0)],
dashPhase: phaseAnimation ? (size - lineWidth) * CGFloat.pi / CGFloat(dashCount) : .zero))
.frame(width: size, height: size)
.animation(phaseAnimation ? Animation.linear(duration: 1).repeatForever(autoreverses: false) : Animation.interactiveSpring, value: phaseAnimation)
Spacer()
Button(phaseAnimation ? "Pause Animation" : "Run Animation") {
phaseAnimation.toggle()
}
}
.padding()
}
}
这种缺陷是因为虚线没有完全填满整个路径的长度。如果你使用与路径长度成正比的虚线大小,效果会很好。例如,
400 - lineWidth
是圆的直径。请记住,strokeBorder
将形状插入lineWidth / 2
,因此圆的直径lineWidth
较小。通过将圆的周长除以偶数,我确保虚线完全填满整个路径。路径的长度计算起来可能比较棘手,而且您必须使用不均匀的虚线大小。您仍然可以通过在路径的起始位置设置动画来使虚线正确移动,因为那是虚线的起始位置。
内置
Circle
总是从圆圈的右侧开始,这就是为什么奇怪的视觉效果总是发生在那里。这里我创建了一个
MyCircle
可以控制起点的,它可以像这样动画: