Skip to content

Instantly share code, notes, and snippets.

@iAmVishal16
Created October 27, 2023 14:39
Show Gist options
  • Select an option

  • Save iAmVishal16/b4bb22e20f68f923470d29702e210e39 to your computer and use it in GitHub Desktop.

Select an option

Save iAmVishal16/b4bb22e20f68f923470d29702e210e39 to your computer and use it in GitHub Desktop.
Rainbow Spiral in SwiftUI. Use apple Playground app for best result.
//
// Spiral.swift
// ShapeAnimation
//
// Created by Vishal Paliwal on 27/06/23.
//
import SwiftUI
struct SpiralView: View {
@State private var animate = false
@State private var angle: Double = 360.0
var body: some View {
ZStack {
Color.black
.ignoresSafeArea(edges: .all)
ForEach(0..<20, id: \.self) { index in
Spiral(circleCount: 64, circleRadius: 5, circleSpacing: Double(index) * 10)
.rotationEffect(.degrees(Double(index) * 5), anchor: .center)
.rotationEffect(.degrees(animate ? angle : -360), anchor: .center)
.hueRotation(Angle(degrees: animate ? angle : 0))
.animation(.easeInOut(duration: 2.5).delay(0.1 * Double(index)), value: animate)
}
}
.onChange(of: animate, perform: { value in
DispatchQueue.main.asyncAfter(deadline: .now() + 2.5) {
withAnimation(Animation.easeOut(duration: 2.5).repeatForever(autoreverses: true)) {
self.animate.toggle()
}
}
})
.onAppear(perform: {
DispatchQueue.main.asyncAfter(deadline: .now() + 2.5) {
animate.toggle()
}
})
}
}
struct Spiral: View {
@State private var animate = false
let circleCount: Int // Number of circles to display
let circleRadius: CGFloat // Radius of each circle
let circleSpacing: CGFloat // Spacing between circles
init(circleCount: Int, circleRadius: CGFloat, circleSpacing: CGFloat) {
self.circleCount = circleCount
self.circleRadius = circleRadius
self.circleSpacing = circleSpacing
}
var body: some View {
GeometryReader(content: { geometry in
ZStack {
ForEach(0..<circleCount, id: \.self) { index in
let angle = 2 * .pi / Double(circleCount) * Double(index)
let xOffset = cos(angle) * Double(circleRadius + circleSpacing)
let yOffset = sin(angle) * Double(circleRadius + circleSpacing)
Circle()
.foregroundColor(.yellow)
.frame(width: Double(index) * 0.03 * circleRadius)
.position(x: geometry.size.width / 2 + CGFloat(xOffset),
y: geometry.size.height / 2 + CGFloat(yOffset))
.opacity(0.1 * Double(index))
.rainbow()
}
}
})
}
}
struct Spiral_Previews: PreviewProvider {
static var previews: some View {
SpiralView()
.preferredColorScheme(.dark)
}
}
struct Rainbow: ViewModifier {
let hueColors = stride(from: 0, to: 1, by: 0.01).map {
Color(hue: $0, saturation: 1, brightness: 1)
}
func body(content: Content) -> some View {
content
.overlay(GeometryReader { (proxy: GeometryProxy) in
ZStack {
LinearGradient(gradient: Gradient(colors: self.hueColors),
startPoint: .leading,
endPoint: .trailing)
.frame(width: proxy.size.width)
}
})
.mask(content)
}
}
extension View {
func rainbow() -> some View {
self.modifier(Rainbow())
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment