import SwiftUI struct DragNDropDotsView: View { @State private var gridColumns = Array(repeating: GridItem(.flexible()), count: 15) @State private var colors = [Color.pink, Color.mint, Color.orange, Color.teal, Color.yellow, Color.cyan, Color.purple, Color.blue] @State private var offset = CGSize.zero @State private var scaleFactor : CGFloat = 1 @State private var isAnimating : Bool = true let springAnimation = Animation.spring(response: 0.4, dampingFraction: 0.5, blendDuration: 0.3) let numCircles = 375 let animationSpeed : Double = 400 let scaleIncrease = 0.2 var body: some View { VStack { VStack{ Spacer() LazyVGrid(columns: gridColumns) { ForEach((0..<numCircles).indices, id: \.self) { index in Circle() .foregroundColor(colors.randomElement()) .offset(offset) .scaleEffect(scaleFactor) .animation(springAnimation.delay(Double(index) / animationSpeed), value: offset) } } .gesture(DragGesture() .onChanged({ drag in offset = drag.translation isAnimating = true })) Spacer() } .navigationTitle("Drag n' Drop It") .navigationBarTitleDisplayMode(.inline) .clipShape(Rectangle()) .safeAreaInset(edge: .top, spacing: 0) { Color.clear.frame(height: 0) } .safeAreaInset(edge: .bottom, spacing: 0) { Color.clear.frame(height: 0) } }.onAppear(perform: { withAnimation(.spring(response: 0.6, dampingFraction: 0.5, blendDuration: 1).repeatForever()) { resetValues() } }) } func resetValues() { scaleFactor = 1 offset = .zero } } struct DragnDropDots_Previews: PreviewProvider { static var previews: some View { DragNDropDotsView() } }