Last active
October 31, 2020 23:46
-
-
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!
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
// 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() | |
} | |
} |
Author
kieranb662
commented
Oct 31, 2020
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment