Created
February 28, 2025 14:08
-
-
Save 1998code/df9d7609603f5b1eb7f6e47ce6dd381e to your computer and use it in GitHub Desktop.
Shimmer Effect 2025
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
// Copyright © 2025 MING | |
// MIT License | |
import SwiftUI | |
struct ContentView: View { | |
@State private var colorful: Bool = true | |
@State private var dragLocation: CGPoint = .zero | |
var body: some View { | |
ZStack { | |
Color.black.edgesIgnoringSafeArea(.all) | |
Text("Shimmer Effect \non \(Text("SwiftUI").foregroundColor(.white))") | |
.font(.largeTitle) | |
.fontWeight(.heavy) | |
.foregroundColor(.secondary) | |
.multilineTextAlignment(.center) | |
.opacity(dragLocation == .zero ? 1 : 0.1) | |
DotGrid(colorful: $colorful, dragLocation: $dragLocation) | |
.background(.gray.opacity(0.1)) | |
.cornerRadius(36) | |
.padding() | |
.gesture( | |
DragGesture() | |
.onChanged { value in | |
withAnimation { | |
dragLocation = value.location | |
} | |
} | |
.onEnded { _ in | |
withAnimation { | |
dragLocation = .zero | |
} | |
} | |
) | |
} | |
} | |
} | |
struct DotGrid: View { | |
@Binding var colorful: Bool | |
@Binding var dragLocation: CGPoint | |
let rows = 25 | |
let columns = 25 | |
let dotSize: CGFloat = 5 | |
var body: some View { | |
GeometryReader { geometry in | |
let spacingX = (geometry.size.width - (CGFloat(columns) * dotSize)) / CGFloat(columns + 1) | |
let spacingY = (geometry.size.height - (CGFloat(rows) * dotSize)) / CGFloat(rows + 1) | |
let dots = (0..<rows).flatMap { row in | |
(0..<columns).map { col in | |
CGPoint(x: spacingX + CGFloat(col) * (dotSize + spacingX) + dotSize / 2, | |
y: spacingY + CGFloat(row) * (dotSize + spacingY) + dotSize / 2) | |
} | |
} | |
ForEach(dots, id: \.self) { dot in | |
Circle() | |
.fill(colorForDotCenter(at: dot)) | |
.frame(width: dotSize, height: dotSize) | |
.position(dot) | |
.shadow( | |
color: colorForDot(at: dot), | |
radius: 3 | |
) | |
} | |
} | |
} | |
private func colorForDot(at dot: CGPoint) -> Color { | |
guard dragLocation != .zero else { return Color.clear } | |
let distance = hypot(dot.x - dragLocation.x, dot.y - dragLocation.y) | |
let maxDistance: CGFloat = 250 | |
let opacity = max(0, 1 - (distance / maxDistance)) | |
return Color.white.opacity(opacity) | |
} | |
private func colorForDotCenter(at dot: CGPoint) -> Color { | |
guard dragLocation != .zero else { return Color.gray.opacity(0.15) } | |
let distance = hypot(dot.x - dragLocation.x, dot.y - dragLocation.y) | |
let maxDistance: CGFloat = 250 | |
let opacity = max(0.05, 1 - (distance / maxDistance)) | |
return colorful ? Color( | |
red: Double.random(in: 0...1), | |
green: Double.random(in: 0...1), | |
blue: Double.random(in: 0...1) | |
).opacity(opacity) | |
: Color.blue.opacity(opacity) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment