Skip to content

Instantly share code, notes, and snippets.

@Koshimizu-Takehito
Created June 29, 2024 11:13
Show Gist options
  • Save Koshimizu-Takehito/2253fcba7a2c817131969fd69ba4bb12 to your computer and use it in GitHub Desktop.
Save Koshimizu-Takehito/2253fcba7a2c817131969fd69ba4bb12 to your computer and use it in GitHub Desktop.
MeshGradient サンプル
import SwiftUI
struct ContentView: View {
@State var id = UUID()
@State var offset = CGSize.zero
@State var control = SIMD2<Float>(0, 0)
var body: some View {
GeometryReader { geometry in
let size = geometry.size
let offset = SIMD2(offset/size)
ZStack {
MeshGradient(
width: 3,
height: 3,
points: [
[0.0, 0.0], [0.5, 0.0], [1.0, 0.0],
[0.0, 0.5], [0.5, 0.5] + control + offset, [1.0, 0.5],
[0.0, 1.0], [0.5, 1.0], [1.0, 1.0]
],
colors: [
.black, .black, .black,
.blue, .blue, .blue,
.green, .green, .green,
]
)
Dot(
id: id,
radius: min(size.width, size.height)/10,
currentOffset: $offset
)
.offset(x: Double(control.x) * size.width, y: Double(control.y) * size.height)
VStack {
HStack {
Spacer()
Button("Reset") {
withAnimation {
self.id = .init()
self.control = .zero
self.offset = .zero
}
}
.foregroundStyle(.white)
.fontWeight(.semibold)
}
Spacer()
Slider(value: $control.x, in: (-(0.5 + offset.x)...(0.5 - offset.x)))
Slider(value: $control.y, in: (-(0.5 + offset.y)...(0.5 - offset.y)))
}
.padding()
.padding()
}
.ignoresSafeArea()
}
}
}
struct Dot: View {
let id: UUID
let radius: Double
@State private var offsets = (dragging: CGSize.zero, last: CGSize.zero)
@Binding var currentOffset: CGSize
var body: some View {
Circle()
.frame(width: radius)
.foregroundStyle(.white.opacity(1/1024))
.gesture(
DragGesture()
.onChanged {
offsets.dragging = $0.translation
currentOffset = offsets.last + offsets.dragging
}
.onEnded { _ in
offsets.last += offsets.dragging
offsets.dragging = .zero
currentOffset = offsets.last + offsets.dragging
}
)
.offset(offsets.last)
.background {
Circle()
.frame(width: radius)
.foregroundStyle(.orange.mix(with: .pink, by: 0.45))
.offset(currentOffset)
}
.onChange(of: id) { _, _ in
offsets = (.zero, .zero)
}
}
}
extension CGSize {
static func+(_ lhs: Self, _ rhs: Self) -> Self {
self.init(width: lhs.width + rhs.width, height: lhs.height + rhs.height)
}
static func-(_ lhs: Self, _ rhs: Self) -> Self {
self.init(width: lhs.width - rhs.width, height: lhs.height - rhs.height)
}
static func/(_ lhs: Self, _ rhs: Self) -> Self {
self.init(width: lhs.width / rhs.width, height: lhs.height / rhs.height)
}
static func*(_ lhs: CGFloat, _ rhs: Self) -> Self {
self.init(width: lhs * rhs.width, height: lhs * rhs.height)
}
static func+=(lhs: inout Self, rhs: Self) {
lhs = lhs + rhs
}
}
extension SIMD2<Float> {
init(_ v: CGSize) {
self.init(x: Float(v.width), y: Float(v.height))
}
}
#Preview {
ContentView()
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment