Skip to content

Instantly share code, notes, and snippets.

@kieranb662
Last active October 31, 2020 23:46
Show Gist options
  • Save kieranb662/6b2f175e9bdfa3edc202f03600fe5efa to your computer and use it in GitHub Desktop.
Save kieranb662/6b2f175e9bdfa3edc202f03600fe5efa to your computer and use it in GitHub Desktop.
A toggle switch that looks like an Eye opening and closing. Happy Halloween!
// Swift toolchain version 5.0
// Running macOS version 10.15
// Created on 10/31/20.
//
// Author: Kieran Brown
//
import SwiftUI
struct EyeOutline: Shape {
var upperOffset: CGFloat = 0
var lowerOffset: CGFloat = 0
var animatableData: AnimatablePair<CGFloat, CGFloat> {
get {AnimatablePair(upperOffset, lowerOffset)}
set {
self.upperOffset = newValue.first
self.lowerOffset = newValue.second
}
}
func path(in rect: CGRect) -> Path {
let w = rect.width
let h = rect.height
return Path { path in
path.move(to: CGPoint(x: 0, y: h/2))
path.addQuadCurve(to: CGPoint(x: w, y: h/2), control: CGPoint(x: w/2, y: h/4))
path.addQuadCurve(to: CGPoint(x: 0, y: h/2), control: CGPoint(x: w/2, y: h/(4 - 2*upperOffset)))
path.closeSubpath()
path.addQuadCurve(to: CGPoint(x: w, y: h/2), control: CGPoint(x: w/2, y: 3*h/4))
path.addQuadCurve(to: CGPoint(x: 0, y: h/2), control: CGPoint(x: w/2, y: (3-lowerOffset)*h/(4)))
path.closeSubpath()
}
}
}
struct EyeShape: Shape {
func path(in rect: CGRect) -> Path {
let w = rect.width
let h = rect.height
return Path { path in
path.move(to: CGPoint(x: 0, y: h/2))
path.addQuadCurve(to: CGPoint(x: w, y: h/2), control: CGPoint(x: w/2, y: h/4))
path.addQuadCurve(to: CGPoint(x: 0, y: h/2), control: CGPoint(x: w/2, y: 3*h/4))
path.closeSubpath()
}
}
}
struct EyeView: View {
@Binding var isOpen: Bool
let scleraColor = Color.white
let eyeLidColor = Color(white: 0.8)
let irisGradient = RadialGradient(
gradient: Gradient(colors: [Color(red: 0, green: 0.5, blue: 0.8), Color(red: 0.3, green: 0.5, blue: 0.8)]),
center: .center,
startRadius: 5,
endRadius: 100
)
var offset: CGFloat { isOpen ? 0.2 : 0.96 }
var body: some View {
GeometryReader { proxy in
ZStack {
EyeShape()
.fill(scleraColor)
.shadow(radius: 3)
Circle()
.stroke(irisGradient, lineWidth: 0.7*proxy.size.width/4)
.frame(width: proxy.size.width/4)
EyeOutline(upperOffset: offset,
lowerOffset: offset)
.fill(eyeLidColor)
.overlay(EyeOutline(upperOffset: offset,
lowerOffset: offset)
.stroke(eyeLidColor, style: StrokeStyle(lineWidth: 4, lineJoin: .round)))
}
.contentShape(Rectangle())
.onTapGesture(perform: { self.isOpen.toggle() })
.animation(.spring())
.frame(width: proxy.size.width,
height: proxy.size.width*2)
}
}
}
struct EyeExample: View {
@State var isOpen: Bool = true
var body: some View {
EyeView(isOpen: $isOpen).padding()
}
}
struct EyeView_Previews: PreviewProvider {
static var previews: some View {
EyeExample()
}
}
@kieranb662
Copy link
Author

output

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment