Skip to content

Instantly share code, notes, and snippets.

@DarrenHurst
Created March 27, 2023 20:13
Show Gist options
  • Save DarrenHurst/3e8c05264e4fe0184acf990f82eb05c3 to your computer and use it in GitHub Desktop.
Save DarrenHurst/3e8c05264e4fe0184acf990f82eb05c3 to your computer and use it in GitHub Desktop.
A few simple animations on spot, and ms kitty.
import Foundation
import SwiftUI
@available(iOS 16.0, *)
struct AnimalPictures: View {
@State var profileImg: ProfileImgType = .teddybear
var body: some View {
VStack{
HStack {
FunView(.white, backColor: Color.green)
.shadow(radius: 5)
Text("VS").font(.headline)
.foregroundColor(.black)
FunView(.white, backColor: Color.green)
.shadow(radius: 5)
}
.border(.gray, width: 1)
.padding(5)
.cornerRadius(4)
}
}
}
@available(iOS 16.0, *)
enum ProfileImgType {
case cat, koala, teddybear, dog
}
@available(iOS 13.0, *)
struct Triangle: Shape {
func path(in rect: CGRect) -> Path {
var path :Path = Path()
path.move(to: CGPoint(x:0,y:0))
path.addLine(to: CGPoint(x:15, y:25))
path.addLine(to: CGPoint(x:30, y:0))
path.addLine(to: CGPoint(x:0, y:0))
return path
}
}
@available(iOS 13.0, *)
struct Line: Shape {
func path(in rect: CGRect) -> Path {
var path: Path = Path()
path.move(to: CGPoint(x:0,y:0))
path.addLine(to: CGPoint(x:3, y:18))
return path
}
}
@available(iOS 16.0, *)
struct FunView: View, Identifiable {
var id: UUID = UUID()
@State var viewType: ProfileImgType = .dog
@State var blink: Bool = false
@State var animalColor: Color = .brown
@State var backgroundColor: Color = .brown
@State var whiskers: Bool = false
@State var spot: Bool = false
init(_ color: Color, backColor: Color) {
self.animalColor = color
self.backgroundColor = backColor
}
var body: some View {
VStack {
funProfile(animalColor, backgroundColor, 0.5, viewType)
VStack {
Button("Dog", action: {
viewType = .dog
animalColor = .brown
backgroundColor = .brown
}).foregroundColor(.black)
.padding(.bottom, 4)
.background(viewType == .dog ? .cyan.opacity(0.3): .clear)
Button("Cat", action: {
viewType = .cat
animalColor = .white
backgroundColor = .red
}).foregroundColor(.black)
.padding(.bottom, 4)
.background(viewType == .cat ? .cyan.opacity(0.3): .clear)
Button("Teddy", action: {
viewType = .teddybear
animalColor = .orange
backgroundColor = .green
}).foregroundColor(.black)
.padding(.bottom, 4)
.background(viewType == .teddybear ? .cyan.opacity(0.3): .clear)
Button("Koala", action: {
viewType = .koala
animalColor = .gray
backgroundColor = .yellow
}).foregroundColor(.black)
.padding(.bottom, 4)
.background(viewType == .koala ? .cyan.opacity(0.3): .clear)
}.padding(20)
}.padding(10)
}
public func baseColor(color: Color) -> any ShapeStyle {
LinearGradient(
gradient: Gradient(
colors: [.brown,color,color,.clear, .clear]),
startPoint: .top, endPoint: .bottom
)
}
}
@available(iOS 16.0, *)
extension FunView {
fileprivate func funProfile(_ base: Color, _ color: Color, _ opacity: Double, _ viewType: ProfileImgType) -> some View {
let bearColor: Color = base
return ZStack {
animalHead(bearColor, viewType)
.rotationEffect( Angle(degrees: 80) )
.frame(width:50).scaledToFit().offset(y:10).zIndex(0.2)
ZStack {
AnyView(
Circle()
.fill(baseColor(color: bearColor))
.frame(width: 47).offset(y:50)
.scaleEffect(x: 1.2, y: 2, anchor: .bottom))
AnyView(
Circle()
.fill(baseColor(color: bearColor))
.frame(width: 47).offset(x:20, y:50).scaleEffect(x: 1.1, y: 1.3, anchor: .bottom))
AnyView(
Circle()
.fill(baseColor(color: bearColor))
.frame(width: 47).offset(x:-20, y:50).scaleEffect(x: 1.1, y: 1.4, anchor: .bottom))
}.zIndex(0.1)
animalHead(bearColor.opacity(0.5), viewType).controlSize(.small)
.rotationEffect( Angle(degrees: 80) )
.frame(width:50).scaledToFit().offset(y:10).zIndex(0.2)
}.frame(width: 100, height:120)
.background(.white.opacity(0.05))
.background(color.opacity(opacity))
.mask(Circle())
.shadow(radius: 2)
}
fileprivate func face(_ color: Color) -> some View {
ZStack {
Circle().frame(width:10).offset(x:5).zIndex(0.2)
Circle().frame(width:2).offset(x:15).zIndex(0.2)
Circle().fill().frame(height: 5).offset(x: -1, y: 10).opacity(0.3).zIndex(0.2)
Circle().fill().frame(height: 5).offset(x: 3, y: -10).opacity(0.5).zIndex(0.2)
Circle()
.fill(RadialGradient.init(colors: [color.opacity(0.6), color.opacity(1), color.opacity(0.8)], center: .top, startRadius: 10.0, endRadius: 90.0))
.opacity(blink ? 0.7 : 0.6)
.animation(.default.speed(0.5).repeatForever(), value: blink).zIndex(0.6)
}
}
fileprivate func ears(_ color: Color) -> some View {
ZStack {
Circle().fill(LinearGradient(gradient: Gradient(colors: [color, .clear, .clear]), startPoint: .bottomLeading, endPoint: .topTrailing).opacity(0.9))
.zIndex(0.2)
.frame(width:35)
.offset(x:-15, y: 13)
Circle().fill(LinearGradient(gradient: Gradient(colors: [color, .clear, .clear]), startPoint: .topLeading, endPoint: .bottomTrailing).opacity(0.9))
.zIndex(0.2)
.frame(width:35)
.offset(x:-12, y: -15)
}
}
fileprivate func builderCircle(_ color: Color) -> some View {
return Circle().stroke(lineWidth: 13).fill(color.opacity(0.2)).transformEffect(CGAffineTransform(a: 0.2, b: -0.2, c: 0.4, d: 0.4, tx: -2, ty: 31)).rotationEffect(Angle(degrees: 49)).shadow(radius: 5)
}
fileprivate func whiskersView() -> some View {
ZStack {
Line()
.stroke(style: StrokeStyle(lineWidth: 1))
.fill(.gray)
.offset(x:30, y:24)
.shadow(radius: 5)
Line()
.stroke(style: StrokeStyle(lineWidth: 1))
.fill(.gray)
.offset(x:-12, y:35)
.rotationEffect(Angle(degrees: 45), anchor: .bottom)
.shadow(radius: 5)
Line()
.stroke(style: StrokeStyle(lineWidth: 1))
.fill(.gray)
.offset(x:34, y:60)
.shadow(radius: 5)
Line()
.stroke(style: StrokeStyle(lineWidth: 1))
.fill(.gray)
.offset(x:10, y:62)
.rotationEffect(Angle(degrees: 34), anchor: .bottom)
.shadow(radius: 5)
}
}
fileprivate func animalHead(_ color: Color, _ viewType: ProfileImgType) ->
some View {
ZStack {
ZStack {
if [.dog, .teddybear, .koala].contains(viewType) {
ears(color)
}
if [.dog].contains(viewType) {
//white face
Circle()
.fill(.white)
.frame(width: 50, height: 100)
//snoot
Circle()
.fill(.gray)
.frame(width: 50, height: 20).offset(x:10)
//Spot
Circle()
.fill(.gray.opacity(0.4))
.frame(width: 50, height: spot ? 20 : 30).offset(x:-3, y:10)
.animation(.default.repeatCount(3), value: spot)
.onAppear() {
spot = true
}
.onDisappear() {
spot = false
}
}
face(color)
if viewType == .cat {
Triangle().fill(LinearGradient(gradient: Gradient(colors: [.white, .clear]), startPoint: .bottom, endPoint: .top))
.frame(width: 25).scaledToFit()
.rotationEffect(Angle(degrees: 66))
.offset(x:-30, y:10)
.shadow(radius: 2)
Triangle()
.fill(LinearGradient(gradient: Gradient(colors: [.clear, .white, .white, .white]), startPoint: .topLeading, endPoint: .bottomLeading))
.frame(width: 5).scaledToFit()
.rotationEffect(Angle(degrees: 6)).offset(x:-44, y:19)
ZStack{
whiskersView().rotationEffect(Angle(degrees: whiskers ? 0 : 15))
.animation(.default.repeatCount(10).speed(0.5), value: whiskers)
.onAppear() {
whiskers = true
}
.onDisappear() {
whiskers = false
}
}.zIndex(0.1)
.shadow(radius: 5)
}
}.zIndex(0.05)
.shadow(radius: blink ? 0 : 2)
.animation(.default.speed(0.1).repeatForever(), value: blink)
.zIndex(0.1)
.offset( y: blink ? 0 : 0.1)
.animation(.default.speed(0.1).repeatForever(), value: blink)
.onAppear(){
blink = true
}
}.onAppear() {
blink = blink ? false : true
}
}
}
@available(iOS 16.0, *)
struct AnimalPicturePreview: PreviewProvider {
static var previews: some View {
AnimalPictures()
}
}
@DarrenHurst
Copy link
Author

Screen.Recording.2023-03-27.at.4.06.28.PM.mov

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