From dc03b27d2540b324531735e882bf180cac246bb5 Mon Sep 17 00:00:00 2001 From: Mert Tecimen Date: Thu, 8 Sep 2022 18:40:35 +0300 Subject: [PATCH] Challenge completed. --- .../contents.xcworkspacedata | 7 + .../xcshareddata/IDEWorkspaceChecks.plist | 8 + .../ContentView + ViewModel.swift | 82 ++++++++++ Fire Animation.swiftpm/ContentView.swift | 53 +++++++ Fire Animation.swiftpm/FireView.swift | 141 ++++++++++++++++++ Fire Animation.swiftpm/FusePathView.swift | 46 ++++++ Fire Animation.swiftpm/FuseView.swift | 55 +++++++ Fire Animation.swiftpm/MyApp.swift | 17 +++ Fire Animation.swiftpm/Package.swift | 43 ++++++ 9 files changed, 452 insertions(+) create mode 100644 Fire Animation.swiftpm/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata create mode 100644 Fire Animation.swiftpm/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist create mode 100644 Fire Animation.swiftpm/ContentView + ViewModel.swift create mode 100644 Fire Animation.swiftpm/ContentView.swift create mode 100644 Fire Animation.swiftpm/FireView.swift create mode 100644 Fire Animation.swiftpm/FusePathView.swift create mode 100644 Fire Animation.swiftpm/FuseView.swift create mode 100644 Fire Animation.swiftpm/MyApp.swift create mode 100644 Fire Animation.swiftpm/Package.swift diff --git a/Fire Animation.swiftpm/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata b/Fire Animation.swiftpm/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata new file mode 100644 index 0000000..919434a --- /dev/null +++ b/Fire Animation.swiftpm/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata @@ -0,0 +1,7 @@ + + + + + diff --git a/Fire Animation.swiftpm/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist b/Fire Animation.swiftpm/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist new file mode 100644 index 0000000..18d9810 --- /dev/null +++ b/Fire Animation.swiftpm/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist @@ -0,0 +1,8 @@ + + + + + IDEDidComputeMac32BitWarning + + + diff --git a/Fire Animation.swiftpm/ContentView + ViewModel.swift b/Fire Animation.swiftpm/ContentView + ViewModel.swift new file mode 100644 index 0000000..0156623 --- /dev/null +++ b/Fire Animation.swiftpm/ContentView + ViewModel.swift @@ -0,0 +1,82 @@ +// +// ContentView + ViewModel.swift +// Fire Animation +// +// Created by Mert Tecimen on 7.09.2022. +// + +import Foundation +import SwiftUI + +extension ContentView{ + class ViewModel: ObservableObject{ + var fuseSegments: [CGPoint] + var radialGradient: RadialGradient + var largeRadialGradient: RadialGradient + @Published var xOffset: CGFloat + @Published var yOffset: CGFloat + @Published var rotationDegree: CGFloat + @Published var isFuseVisible: Bool + @Published var textColor: Color = .white + var fuseDelay: Double + + init(fuseDelay: Double = 1.0){ + self.xOffset = 0.5 + self.yOffset = 0 + fuseSegments = [] + let duoGradient = Gradient(colors: [.yellow, .black]) + self.radialGradient = .radialGradient(duoGradient, center: .center, startRadius: 10, endRadius: 50) + self.largeRadialGradient = .radialGradient(duoGradient, center: .center, startRadius: 0, endRadius: 300) + self.rotationDegree = 0 + self.fuseDelay = fuseDelay + self.isFuseVisible = true + generateFuseSegments() + } + + private func generateFuseSegments(){ + for index in 0..{ + get{ .init(x, y) } + set{ + x = newValue.first + y = newValue.second + } + } + + init(animatableData: AnimatablePair = .init(0.5, 0) ) { + self.animatableData = animatableData + } + + + func path(in rect: CGRect) -> Path { + return Path { path in + + path.move(to: .init( + x: rect.width * x, + y: rect.height * y) + ) + + path.addCurve( + to: .init( + x: rect.width * 1, + y: rect.height * 0.7 + ), + control1: .init( + x: rect.width * 0.6, + y: rect.height * 0 + ), + control2: .init( + x: rect.width * 0.9, + y: rect.height * 0.5 + ) + ) + + path.addCurve( + to: .init( + x: rect.width * 0.5, + y: rect.height * 1 + ), + control1: .init( + x: rect.width * 1, + y: rect.height * 0.7 + ), control2: .init( + x: rect.width * 1, + y: rect.height * 1 + ) + ) + + path.addCurve( + to: .init( + x: rect.width * 0, + y: rect.height * 0.7 + ), + control1: .init( + x: rect.width * 0, + y: rect.height * 1 + ), control2: .init( + x: rect.width * 0, + y: rect.height * 0.7 + ) + ) + + + + path.addCurve( + to: .init( + x: rect.width * x, + y: rect.height * y + ), + control1: .init( + x: rect.width * 0.1, + y: rect.height * 0.5 + ), control2: .init( + x: rect.width * 0.40, + y: rect.height * 0 + ) + ) + + + + + } + } + +} + +struct FireView: View { + @State private var flameMotion: AnimatablePair = .init(0.5, 0) + let timer = Timer.publish(every: 0.2, on: .main, in: .default).autoconnect() + var body: some View { + GeometryReader{ geometry in + ZStack(alignment: .topLeading){ + + FlameShape(animatableData: .init(flameMotion.first * CGFloat.random(in: 0.5...1.5), flameMotion.second * CGFloat.random(in: -0.5...1))) + .fill(Color.orange) + .opacity(0.6) + .rotationEffect(Angle(degrees: -10), anchor: .init(x: 0, y: 0.7)) + .offset(.init(width: 0, height: 0.35 * geometry.size.height)) + .frame(width: geometry.size.width / 2, height: geometry.size.height / 2) + + FlameShape(animatableData: flameMotion) + .fill(Color.orange) + .frame(width: geometry.size.width, height: geometry.size.height) + .onReceive(timer){ _ in + withAnimation(.linear(duration: 0.2)){ + flameMotion = .init(CGFloat.random(in: 0.2...0.7), CGFloat.random(in: -0.2...0)) + } + } + + FlameShape(animatableData: flameMotion) + .fill(Color.yellow) + .offset(.init(width: geometry.size.width / 4, height: 0.35 * geometry.size.height)) + .frame(width: geometry.size.width / 2, height: geometry.size.height / 2) + + + } + } + } +} + +struct FireView_Previews: PreviewProvider { + static var previews: some View { + FireView() + } +} diff --git a/Fire Animation.swiftpm/FusePathView.swift b/Fire Animation.swiftpm/FusePathView.swift new file mode 100644 index 0000000..86174e3 --- /dev/null +++ b/Fire Animation.swiftpm/FusePathView.swift @@ -0,0 +1,46 @@ +// +// FusePathView.swift +// Fire Animation +// +// Created by Mert Tecimen on 7.09.2022. +// + +import SwiftUI + +struct FusePathView: View { + + let width: CGFloat + let height: CGFloat + let fuseSegments: [CGPoint] + let strokeColor: Color + + init(width: CGFloat, height: CGFloat, fuseSegments: [CGPoint], strokeColor: Color = .black) { + self.width = width + self.height = height + self.fuseSegments = fuseSegments + self.strokeColor = strokeColor + } + + var body: some View { + Path { path in + // Top middle start point. + path.move( + to: CGPoint( + x: width * 0.5, + y: height * 0.0 + ) + ) + + fuseSegments.forEach { segment in + path.addLine( + to: CGPoint( + x: width * segment.x, + y: height * segment.y + ) + ) + } + } + .stroke(strokeColor) + } +} + diff --git a/Fire Animation.swiftpm/FuseView.swift b/Fire Animation.swiftpm/FuseView.swift new file mode 100644 index 0000000..045fdcd --- /dev/null +++ b/Fire Animation.swiftpm/FuseView.swift @@ -0,0 +1,55 @@ +// +// FuseView.swift +// Fire Animation +// +// Created by Mert Tecimen on 6.09.2022. +// + +import SwiftUI + +struct FuseView: View { + @State private var scaleFactor1: CGSize = .init(width: 1, height: 1) + @State private var scaleFactor2: CGSize = .init(width: 0.5, height: 0.5) + @State private var rotationDegree: CGFloat = 0 + + var body: some View { + GeometryReader { geometry in + ZStack() { + Circle() + .foregroundColor(.orange) + .scaleEffect(scaleFactor2) + .offset(y: -geometry.size.width * 1.7) + Circle() + .foregroundColor(.orange) + .scaleEffect(scaleFactor1) + .offset(y: -geometry.size.width * 1) + ZStack{ + Circle() + .foregroundColor(.orange) + Circle() + .foregroundColor(.yellow) + .frame(width: geometry.size.width * 4/6) + } + + } + + .frame(width: geometry.size.width) + .onAppear{ + withAnimation(.linear(duration: 0.6).repeatForever(autoreverses: false).delay(0)){ + self.scaleFactor1 = .init(width: 0.1, height: 0.1) + } + withAnimation(.linear(duration: 0.6).repeatForever(autoreverses: false).delay(0.1)){ + self.scaleFactor2 = .init(width: 0.1, height: 0.1) + } + } + } + + } + +} + +struct FuseView_Previews: PreviewProvider { + static var previews: some View { + FuseView() + } +} diff --git a/Fire Animation.swiftpm/MyApp.swift b/Fire Animation.swiftpm/MyApp.swift new file mode 100644 index 0000000..5e69b00 --- /dev/null +++ b/Fire Animation.swiftpm/MyApp.swift @@ -0,0 +1,17 @@ +import SwiftUI + +@main +struct MyApp: App { + @State var isStarted: Bool = false + var body: some Scene { + WindowGroup { + ContentView(isStarted: $isStarted) + .background(.black) + .onTapGesture { + if !isStarted{ + isStarted.toggle() + } + } + } + } +} diff --git a/Fire Animation.swiftpm/Package.swift b/Fire Animation.swiftpm/Package.swift new file mode 100644 index 0000000..66b95c6 --- /dev/null +++ b/Fire Animation.swiftpm/Package.swift @@ -0,0 +1,43 @@ +// swift-tools-version: 5.6 + +// WARNING: +// This file is automatically generated. +// Do not edit it by hand because the contents will be replaced. + +import PackageDescription +import AppleProductTypes + +let package = Package( + name: "Fire Animation", + platforms: [ + .iOS("15.2") + ], + products: [ + .iOSApplication( + name: "Fire Animation", + targets: ["AppModule"], + bundleIdentifier: "Mert-Tecimen.Fire-Animation", + teamIdentifier: "R2MF39ASQT", + displayVersion: "1.0", + bundleVersion: "1", + appIcon: .placeholder(icon: .bicycle), + accentColor: .presetColor(.orange), + supportedDeviceFamilies: [ + .pad, + .phone + ], + supportedInterfaceOrientations: [ + .portrait, + .landscapeRight, + .landscapeLeft, + .portraitUpsideDown(.when(deviceFamilies: [.pad])) + ] + ) + ], + targets: [ + .executableTarget( + name: "AppModule", + path: "." + ) + ] +)