Created
January 1, 2026 22:16
-
-
Save radiofun/943b67f19cfe9eb62729d77f113cc892 to your computer and use it in GitHub Desktop.
Distortion Sample view to use Distortion Shader
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 DistortionSampleView: View { | |
| @State private var dragP : CGPoint = .init(x: -1000, y: -1000) | |
| var body: some View { | |
| ZStack { | |
| // Black Background - replace with image, gradient, whatever you like. | |
| Color.black | |
| // Visualizing the "100 control points" (10x10 grid) | |
| Canvas { context, size in | |
| let rows = 10 | |
| let cols = 10 | |
| // Horizontal lines | |
| for r in 0..<rows { | |
| var path = Path() | |
| for c in 0..<cols { | |
| let x = CGFloat(c) * size.width / CGFloat(cols - 1) | |
| let y = CGFloat(r) * size.height / CGFloat(rows - 1) | |
| if c == 0 { | |
| path.move(to: CGPoint(x: x, y: y)) | |
| } else { | |
| path.addLine(to: CGPoint(x: x, y: y)) | |
| } | |
| } | |
| context.stroke(path, with: .color(.white.opacity(0.5)), lineWidth: 0.2) | |
| } | |
| // Vertical lines | |
| for c in 0..<cols { | |
| var path = Path() | |
| for r in 0..<rows { | |
| let x = CGFloat(c) * size.width / CGFloat(cols - 1) | |
| let y = CGFloat(r) * size.height / CGFloat(rows - 1) | |
| if r == 0 { | |
| path.move(to: CGPoint(x: x, y: y)) | |
| } else { | |
| path.addLine(to: CGPoint(x: x, y: y)) | |
| } | |
| } | |
| context.stroke(path, with: .color(.white.opacity(0.5)), lineWidth: 0.2) | |
| } | |
| // Intersection dots | |
| for r in 0..<rows { | |
| for c in 0..<cols { | |
| let x = CGFloat(c) * size.width / CGFloat(cols - 1) | |
| let y = CGFloat(r) * size.height / CGFloat(rows - 1) | |
| context.fill(Path(ellipseIn: CGRect(x: x-1, y: y-1, width: 1, height: 1)), with: .color(.white.opacity(1.0))) | |
| } | |
| } | |
| } | |
| } | |
| .frame(width:320,height:320) | |
| .cornerRadius(20) | |
| .layerEffect( | |
| ShaderLibrary.distortion( | |
| .boundingRect, | |
| .float2(dragP) | |
| ), | |
| maxSampleOffset: CGSize(width: 100, height: 100) | |
| ) | |
| .gesture( | |
| DragGesture(minimumDistance: 0) | |
| .onChanged { value in | |
| dragP = value.location | |
| } | |
| .onEnded { value in | |
| let centerX: CGFloat = 160 | |
| let centerY: CGFloat = 160 | |
| let dx = value.location.x - centerX | |
| let dy = value.location.y - centerY | |
| let threshold: CGFloat = 100 | |
| var exitX: CGFloat = dx < 0 ? -1000 : 1000 | |
| var exitY: CGFloat = dy < 0 ? -1000 : 1000 | |
| if abs(dx) < threshold { | |
| exitX = centerX | |
| } | |
| if abs(dy) < threshold { | |
| exitY = centerY | |
| } | |
| // Fallback: If both axes are within threshold, force an exit in the direction of the larger delta | |
| if abs(dx) < threshold && abs(dy) < threshold { | |
| if abs(dx) < abs(dy) { | |
| exitX = centerX | |
| exitY = dy < 0 ? -1000 : 1000 | |
| } else { | |
| exitX = dx < 0 ? -1000 : 1000 | |
| exitY = centerY | |
| } | |
| } | |
| withAnimation(.linear(duration: 1.0)) { | |
| dragP = CGPoint(x: exitX, y: exitY) | |
| } | |
| } | |
| ) | |
| } | |
| } | |
| #Preview { | |
| DistortionSampleView() | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment