Skip to content

Instantly share code, notes, and snippets.

@StewartLynch
Created July 9, 2021 05:28
Show Gist options
  • Save StewartLynch/c56b565bb20ee205536904902223fc3c to your computer and use it in GitHub Desktop.
Save StewartLynch/c56b565bb20ee205536904902223fc3c to your computer and use it in GitHub Desktop.
//
// ContentView.swift
// OverlayDrag
//
// Created by Stewart Lynch on 2021-07-08.
//
import SwiftUI
struct ContentView: View {
@State private var layers:[OverlayImage] = [
OverlayImage(imageName: "cloud.drizzle.fill", foreGroundColor: Color.gray, isOnTop: true, scale: 1.5),
OverlayImage(imageName: "sun.min.fill", foreGroundColor: .yellow, isOnTop: false)
]
var body: some View {
VStack {
ZStack {
RoundedRectangle(cornerRadius: 20).fill(Color.green)
ForEach(layers.sorted{ $0.isOnTop && !$1.isOnTop}.reversed()) { layer in
layer.frame(width: 50 * layer.scale)
.offset(x: layer.offset.width + layer.position.width,
y: layer.offset.height + layer.position.height)
.gesture(DragGesture()
.onChanged({ (value) in
let index = layers.firstIndex{$0.isOnTop}!
layers[index].offset.width = value.translation.width
layers[index].offset.height = value.translation.height
}
).onEnded({ value in
let index = layers.firstIndex{$0.isOnTop}!
let newPosX = layers[index].position.width + value.translation.width
let newPosY = layers[index].position.height + value.translation.height
// prevent drag from ending outside of icon background
switch true {
case newPosX < (-(layers[index].scale * 50)):
layers[index].position.width = -(layers[index].scale * 50)
case newPosX > (layers[index].scale * 50):
layers[index].position.width = (layers[index].scale * 50)
default:
layers[index].position.width = newPosX
}
switch true {
case newPosY < (-(layers[index].scale * 50)):
layers[index].position.height = -(layers[index].scale * 50)
case newPosY > (layers[index].scale * 50):
layers[index].position.height = (layers[index].scale * 50)
default:
layers[index].position.height = newPosY
}
layers[index].offset = .zero
})
)
}
}
.clipShape(RoundedRectangle(cornerRadius: 20))
.frame(width: 100, height: 100)
HStack {
ForEach(layers) { layer in
layer.frame(width: 30, height: 30)
.opacity(layer.isOnTop ? 1 : 0.6)
.padding(3)
.border(layer.isOnTop ? Color.gray : Color.clear)
.onTapGesture {
toggleIsOnTop()
}
}
}
}
}
func toggleIsOnTop() {
layers.enumerated().forEach { layerIndex, _ in
layers[layerIndex].isOnTop.toggle()
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
struct OverlayImage: View, Identifiable {
var id = UUID()
var imageName: String
var foreGroundColor: Color
var isOnTop: Bool
var offset: CGSize = .zero
var position: CGSize = .zero
var scale: CGFloat = 1
var body: some View {
Image(systemName: imageName)
.resizable()
.foregroundColor(foreGroundColor)
.aspectRatio(contentMode: .fit)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment