Last active
July 19, 2023 13:37
-
-
Save renyello/8107478347a6f7b77455d453e41b770b to your computer and use it in GitHub Desktop.
HuggingFaceのLoading画面に表示されるアニメーションを再現しました。カラーは青:#3498DB 黄色:#F1C40F 赤:#E74C3C を使用してます。
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import SwiftUI | |
struct HugginFaceProgressCircle: View { | |
@State private var rotationDegrees: [Double] = [0, 0, 0] | |
@State private var startTrim: [CGFloat] = [0, 0, 0] | |
@State private var trimTo: CGFloat = 120.0 / 360.0 | |
@State private var shouldRotate = true | |
@State private var opacity = 1.0 | |
let timer = Timer.publish(every: 0.1, on: .main, in: .common).autoconnect() | |
@State private var percentage: Int = 0 | |
let timer2 = Timer.publish(every: 0.3, on: .main, in: .common).autoconnect() | |
@State private var expandGreenCircle = false | |
var body: some View { | |
ZStack { | |
Text("\(percentage)%") | |
.font(.system(size: 30)) // smaller font size | |
.opacity(opacity) | |
.onReceive(timer2) { _ in | |
if percentage < 100 { | |
percentage += Int.random(in: 1...5) | |
if percentage >= 100 { | |
percentage = 100 | |
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { | |
withAnimation(.linear(duration: 1.0)) { | |
trimTo = 1.0 // Trim all the way when it reaches 100% | |
shouldRotate = false // Stop rotation when it reaches 100% | |
expandGreenCircle = true | |
} | |
DispatchQueue.main.asyncAfter(deadline: .now() + 1) { | |
withAnimation(.linear(duration: 0.4)) { | |
self.opacity = 0 | |
} | |
} | |
} | |
} | |
} | |
} | |
ForEach(0..<3) { index in | |
Circle() | |
.trim(from: 0, to: trimTo) | |
.stroke(lineWidth: 3) | |
.frame(width: CGFloat(100 + 30 * index), height: CGFloat(100 + 30 * index)) | |
.foregroundColor(Color(["Blue","Yellow", "Red"][index])) | |
.rotationEffect(Angle.degrees(CGFloat(index*50)+rotationDegrees[index])) | |
.animation(shouldRotate ? Animation.linear(duration: 1).repeatForever(autoreverses: false) : .default) | |
.opacity(opacity) | |
} | |
} | |
.onAppear() { | |
startTrim = startTrim.map { _ in CGFloat.random(in: 0...1) } | |
} | |
.onReceive(timer) { _ in | |
if shouldRotate { | |
withAnimation(Animation.linear(duration: 1).repeatForever(autoreverses: false)) { | |
rotationDegrees = rotationDegrees.enumerated().map { index, degree in | |
degree + (50.0 * Double(1 - Double(index) * 0.2)) | |
} | |
} | |
} | |
} | |
} | |
} | |
struct HugginFaceProgressCircle_Previews: PreviewProvider { | |
static var previews: some View { | |
HugginFaceProgressCircle() | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment