Ready animation code for IOS app with SwiftUI. You can copy and paste to your project. This is a sample of how I do drawing with bezier curves and animate. All works are based on this principle.

import SwiftUI

 

struct ContentView: View {

    var body: some View {

        freeExampleCode()

    .scaledToFit()

    .frame(width: 300, height: 300) // change size

    }

}

 

struct freeExampleCode: View {

    @State private var speed = 1.0 // change animation speed

    

   @State private var opacityLeaf = 0.0

    @State private var scaleLeaf = 0.4

    @State private var opacitySphere = 0.0

    @State private var scaleSphere = 1.5

    @State private var toggled = false

    func move() {

        if toggled {

            toggled.toggle()

            opacityLeaf = 0.0

            scaleLeaf = 0.4

            opacitySphere = 0.0

            scaleSphere = 1.5

        } else {

            toggled.toggle()

            withAnimation(Animation.easeIn.speed(1 / speed)) { opacityLeaf = 1.0 }

            withAnimation(Animation.easeOut(duration: speed * 2)) { scaleLeaf = 1.0 }

            withAnimation(Animation.linear.speed(1 / speed).delay(speed)) { opacitySphere = 1.0 }

            withAnimation(Animation.interpolatingSpring(stiffness: 500, damping: 5).speed(1 / speed).delay(speed)) { scaleSphere = 1.0 }

        }

    }

 

var body: some View {

        GeometryReader { geo in

            let middle: CGFloat = min(geo.size.width, geo.size.height)

            ZStack {

                // down

                Path { path in

                path.move(to: CGPoint(x: middle * 0.283, y: middle * 0.711))

                path.addCurve(to: CGPoint(x: middle * 0.821, y: middle * 0.696), control1: CGPoint(x: middle * 0.44, y: middle * 0.677), control2: CGPoint(x: middle * 0.656, y: middle * 0.674))

                path.addCurve(to: CGPoint(x: middle * 0.866, y: middle * 0.774), control1: CGPoint(x: middle * 1.005, y: middle * 0.72), control2: CGPoint(x: middle * 1.033, y: middle * 0.772))

                path.addCurve(to: CGPoint(x: middle * 0.29, y: middle * 0.826), control1: CGPoint(x: middle * 0.635, y: middle * 0.775), control2: CGPoint(x: middle * 0.754, y: middle * 0.914))

                path.addCurve(to: CGPoint(x: middle * 0.283, y: middle * 0.711), control1: CGPoint(x: middle * 0.116, y: middle * 0.793), control2: CGPoint(x: middle * 0.144, y: middle * 0.741))

            } .fill(LinearGradient(gradient: Gradient(colors: [Color(red: 225 / 255, green: 69 / 255, blue: 123 / 255), Color(red: 255 / 255, green: 146 / 255, blue: 119 / 255), Color(red: 253 / 255, green: 234 / 255, blue: 238 / 255)]), startPoint: UnitPoint(x: 0.5, y: 0.67), endPoint: UnitPoint(x: 0.5, y: 0.87) ))

            

   // bowl

                Path { path in

                path.addArc(center: CGPoint(x: middle * 0.5, y: middle * 0.524), radius: middle * 0.225, startAngle: .degrees(0), endAngle: .degrees(180), clockwise: false)

             } .fill(LinearGradient(gradient: Gradient(colors: [Color(red: 255 / 255, green: 255 / 255, blue: 255 / 255), Color(red: 252 / 255, green: 163 / 255, blue: 154 / 255)]), startPoint: UnitPoint(x: 0.35, y: 0.43), endPoint: UnitPoint(x: 0.68, y: 0.675) ))

            

                // ellipse

                Path { path in

                path.move(to: CGPoint(x: middle * 0.275, y: middle * 0.524))

                path.addCurve(to: CGPoint(x: middle * 0.725, y: middle * 0.524), control1: CGPoint(x: middle * 0.275, y: middle * 0.44), control2: CGPoint(x: middle * 0.725, y: middle * 0.44))

                path.addCurve(to: CGPoint(x: middle * 0.275, y: middle * 0.524), control1: CGPoint(x: middle * 0.725, y: middle * 0.585), control2: CGPoint(x: middle * 0.275, y: middle * 0.585))

            } .fill(LinearGradient(gradient: Gradient(colors: [Color(red: 225 / 255, green: 69 / 255, blue: 123 / 255), Color(red: 255 / 255, green: 146 / 255, blue: 119 / 255), Color(red: 251 / 255, green: 186 / 255, blue: 166 / 255)]), startPoint: UnitPoint(x: 0.35, y: 0.42), endPoint: UnitPoint(x: 0.72, y: 0.65) ))

            

ZStack {

                // right leaf

                Path { path in

                path.move(to: CGPoint(x: middle * 0.503, y: middle * 0.553))

                path.addCurve(to: CGPoint(x: middle * 0.656, y: middle * 0.327), control1: CGPoint(x: middle * 0.481, y: middle * 0.393), control2: CGPoint(x: middle * 0.578, y: middle * 0.401))

                path.addCurve(to: CGPoint(x: middle * 0.702, y: middle * 0.352), control1: CGPoint(x: middle * 0.704, y: middle * 0.282), control2: CGPoint(x: middle * 0.722, y: middle * 0.258))

                path.addCurve(to: CGPoint(x: middle * 0.503, y: middle * 0.553), control1: CGPoint(x: middle * 0.68, y: middle * 0.453), control2: CGPoint(x: middle * 0.572, y: middle * 0.47))

            } .fill(LinearGradient(gradient: Gradient(colors: [Color(red: 254 / 255, green: 214 / 255, blue: 222 / 255), Color(red: 120 / 255, green: 84 / 255, blue: 247 / 255)]), startPoint: UnitPoint(x: 0.62, y: 0.27), endPoint: UnitPoint(x: 0.62, y: 0.54) ))

           

  // left leaf

                Path { path in

                path.move(to: CGPoint(x: middle * 0.503, y: middle * 0.553))

                path.addCurve(to: CGPoint(x: middle * 0.411, y: middle * 0.508), control1: CGPoint(x: middle * 0.473, y: middle * 0.536), control2: CGPoint(x: middle * 0.43, y: middle * 0.551))

                path.addCurve(to: CGPoint(x: middle * 0.416, y: middle * 0.492), control1: CGPoint(x: middle * 0.408, y: middle * 0.501), control2: CGPoint(x: middle * 0.398, y: middle * 0.468))

                path.addCurve(to: CGPoint(x: middle * 0.503, y: middle * 0.553), control1: CGPoint(x: middle * 0.43, y: middle * 0.514), control2: CGPoint(x: middle * 0.488, y: middle * 0.485))

            } .fill(LinearGradient(gradient: Gradient(colors: [Color(red: 254 / 255, green: 214 / 255, blue: 222 / 255), Color(red: 120 / 255, green: 84 / 255, blue: 247 / 255)]), startPoint: UnitPoint(x: 0.44, y: 0.48), endPoint: UnitPoint(x: 0.47, y: 0.57) ))

         

   // middle leaf

                Path { path in

                path.move(to: CGPoint(x: middle * 0.503, y: middle * 0.553))

                path.addCurve(to: CGPoint(x: middle * 0.385, y: middle * 0.437), control1: CGPoint(x: middle * 0.489, y: middle * 0.529), control2: CGPoint(x: middle * 0.494, y: middle * 0.481))

                path.addCurve(to: CGPoint(x: middle * 0.208, y: middle * 0.285), control1: CGPoint(x: middle * 0.236, y: middle * 0.378), control2: CGPoint(x: middle * 0.304, y: middle * 0.363))

                path.addCurve(to: CGPoint(x: middle * 0.172, y: middle * 0.187), control1: CGPoint(x: middle * 0.027, y: middle * 0.138), control2: CGPoint(x: middle * 0.134, y: middle * 0.179))

                path.addCurve(to: CGPoint(x: middle * 0.503, y: middle * 0.553), control1: CGPoint(x: middle * 0.352, y: middle * 0.225), control2: CGPoint(x: middle * 0.572, y: middle * 0.372))

            } .fill(LinearGradient(gradient: Gradient(colors: [Color(red: 242 / 255, green: 251 / 255, blue: 232 / 255), Color(red: 80 / 255, green: 47 / 255, blue: 196 / 255)]), startPoint: UnitPoint(x: 0.29, y: 0.18), endPoint: UnitPoint(x: 0.31, y: 0.55) ))

            }

            .opacity(opacityLeaf)

            .scaleEffect(scaleLeaf)

                

            // sphere

                Path { path in

                    path.addArc(center: CGPoint(x: middle * 0.51, y: middle * 0.224), radius: middle * 0.077, startAngle: .degrees(0), endAngle: .degrees(360), clockwise: false)

                 } .fill(LinearGradient(gradient: Gradient(colors: [Color(red: 253 / 255, green: 234 / 255, blue: 238 / 255), Color(red: 255 / 255, green: 146 / 255, blue: 119 / 255), Color(red: 225 / 255, green: 69 / 255, blue: 123 / 255)]), startPoint: UnitPoint(x: 0.5, y: 0.147), endPoint: UnitPoint(x: 0.5, y: 0.301) ))

                .opacity(opacitySphere)

                .scaleEffect(scaleSphere)

            }

            .onTapGesture { move() }

        }

    }

}

 

// Line: 88