├── .gitignore
├── LICENSE
├── README.md
├── appleidanimation.swiftpm
├── .swiftpm
│ ├── playgrounds
│ │ ├── DocumentThumbnail.plist
│ │ └── DocumentThumbnail.png
│ └── xcode
│ │ └── package.xcworkspace
│ │ ├── contents.xcworkspacedata
│ │ └── xcshareddata
│ │ └── IDEWorkspaceChecks.plist
├── ContentView.swift
├── MyApp.swift
└── Package.swift
└── assets
├── output.mp4
├── output.png
├── output_square.mov
├── source.mov
└── source.png
/.gitignore:
--------------------------------------------------------------------------------
1 | # Xcode
2 | #
3 | # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore
4 |
5 | ## User settings
6 | xcuserdata/
7 |
8 | ## compatibility with Xcode 8 and earlier (ignoring not required starting Xcode 9)
9 | *.xcscmblueprint
10 | *.xccheckout
11 |
12 | ## compatibility with Xcode 3 and earlier (ignoring not required starting Xcode 4)
13 | build/
14 | DerivedData/
15 | *.moved-aside
16 | *.pbxuser
17 | !default.pbxuser
18 | *.mode1v3
19 | !default.mode1v3
20 | *.mode2v3
21 | !default.mode2v3
22 | *.perspectivev3
23 | !default.perspectivev3
24 |
25 | ## Obj-C/Swift specific
26 | *.hmap
27 |
28 | ## App packaging
29 | *.ipa
30 | *.dSYM.zip
31 | *.dSYM
32 |
33 | ## Playgrounds
34 | timeline.xctimeline
35 | playground.xcworkspace
36 |
37 | # Swift Package Manager
38 | #
39 | # Add this line if you want to avoid checking in source code from Swift Package Manager dependencies.
40 | # Packages/
41 | # Package.pins
42 | # Package.resolved
43 | # *.xcodeproj
44 | #
45 | # Xcode automatically generates this directory with a .xcworkspacedata file and xcuserdata
46 | # hence it is not needed unless you have added a package configuration file to your project
47 | # .swiftpm
48 |
49 | .build/
50 |
51 | # CocoaPods
52 | #
53 | # We recommend against adding the Pods directory to your .gitignore. However
54 | # you should judge for yourself, the pros and cons are mentioned at:
55 | # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control
56 | #
57 | # Pods/
58 | #
59 | # Add this line if you want to avoid checking in source code from the Xcode workspace
60 | # *.xcworkspace
61 |
62 | # Carthage
63 | #
64 | # Add this line if you want to avoid checking in source code from Carthage dependencies.
65 | # Carthage/Checkouts
66 |
67 | Carthage/Build/
68 |
69 | # Accio dependency management
70 | Dependencies/
71 | .accio/
72 |
73 | # fastlane
74 | #
75 | # It is recommended to not store the screenshots in the git repo.
76 | # Instead, use fastlane to re-generate the screenshots whenever they are needed.
77 | # For more information about the recommended setup visit:
78 | # https://docs.fastlane.tools/best-practices/source-control/#source-control
79 |
80 | fastlane/report.xml
81 | fastlane/Preview.html
82 | fastlane/screenshots/**/*.png
83 | fastlane/test_output
84 |
85 | # Code Injection
86 | #
87 | # After new code Injection tools there's a generated folder /iOSInjectionProject
88 | # https://github.com/johnno1962/injectionforxcode
89 |
90 | iOSInjectionProject/
91 |
--------------------------------------------------------------------------------
/LICENSE:
--------------------------------------------------------------------------------
1 | MIT License
2 |
3 | Copyright (c) 2022 An Trinh
4 |
5 | Permission is hereby granted, free of charge, to any person obtaining a copy
6 | of this software and associated documentation files (the "Software"), to deal
7 | in the Software without restriction, including without limitation the rights
8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9 | copies of the Software, and to permit persons to whom the Software is
10 | furnished to do so, subject to the following conditions:
11 |
12 | The above copyright notice and this permission notice shall be included in all
13 | copies or substantial portions of the Software.
14 |
15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 | SOFTWARE.
22 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Apple ID Animation
2 |
3 | Recreating the animation on https://appleid.apple.com using SwiftUI.
4 |
5 | ### Result
6 |
7 | https://user-images.githubusercontent.com/16542463/181802356-7f755f5e-230a-4b16-a986-695e7a7669d3.mov
8 |
9 | ### Comparison
10 |
11 | Result | Reference
12 | --|--
13 |
|
14 |
15 | ### Reference
16 |
17 | https://user-images.githubusercontent.com/16542463/181802881-d1e38ad7-c8be-4f2c-9fe2-1702b6326e38.mov
18 |
19 | Source: https://appleid.apple.com
20 |
--------------------------------------------------------------------------------
/appleidanimation.swiftpm/.swiftpm/playgrounds/DocumentThumbnail.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | DocumentThumbnailConfiguration
6 |
7 | accentColorHash
8 |
9 | ukeIsiaqjcLm3HQki7n2GM+oyVngwmwUe+SPaDmgsIg=
10 |
11 | appIconHash
12 |
13 | n5EWH0NDPkmm3m22gNefYBWfLkrJFyYhoShGQoFYRAs=
14 |
15 | thumbnailIsPrerendered
16 |
17 |
18 |
19 |
20 |
--------------------------------------------------------------------------------
/appleidanimation.swiftpm/.swiftpm/playgrounds/DocumentThumbnail.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atrinh0/appleid-animation/fbb9eb6a536a3a881f5ebc0bc1aa3020dbe0b977/appleidanimation.swiftpm/.swiftpm/playgrounds/DocumentThumbnail.png
--------------------------------------------------------------------------------
/appleidanimation.swiftpm/.swiftpm/xcode/package.xcworkspace/contents.xcworkspacedata:
--------------------------------------------------------------------------------
1 |
2 |
4 |
6 |
7 |
8 |
--------------------------------------------------------------------------------
/appleidanimation.swiftpm/.swiftpm/xcode/package.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 | IDEDidComputeMac32BitWarning
6 |
7 |
8 |
9 |
--------------------------------------------------------------------------------
/appleidanimation.swiftpm/ContentView.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | // Recreating the animation on https://appleid.apple.com using SwiftUI
4 |
5 | struct ContentView: View {
6 | var body: some View {
7 | ZStack {
8 | grayBackground
9 | animatingDots
10 | appleLogo
11 | }
12 | }
13 |
14 | private var grayBackground: some View {
15 | Color(white: 248/255)
16 | .edgesIgnoringSafeArea(.all)
17 | }
18 |
19 | private var animatingDots: some View {
20 | ZStack {
21 | gradientBackground
22 | .mask {
23 | ZStack {
24 | AnimatedDots(delay: 0)
25 | AnimatedDots(delay: 0.25)
26 | .scaleEffect(0.88)
27 | .rotationEffect(.degrees(360/48))
28 | AnimatedDots(delay: 0.5)
29 | .scaleEffect(0.88 * 0.88)
30 | AnimatedDots(delay: 0.75)
31 | .scaleEffect(0.88 * 0.88 * 0.88)
32 | .rotationEffect(.degrees(360/48))
33 | }
34 | }
35 | }
36 | }
37 |
38 | private var gradientBackground: some View {
39 | AngularGradient(colors: [.cyan, .indigo, .pink, .orange, .cyan], center: .center, startAngle: .degrees(-45), endAngle: .degrees(360-45))
40 | }
41 |
42 | private var appleLogo: some View {
43 | Image(systemName: "applelogo")
44 | .foregroundColor(.black)
45 | .font(Font.system(size: 90))
46 | .offset(y: -9)
47 | }
48 | }
49 |
50 | struct AnimatedDots: View {
51 | let delay: Double
52 |
53 | @State private var animating = false
54 | @State private var rotation = 0.0
55 | private let timer = Timer.publish(every: 3, on: .main, in: .common).autoconnect()
56 |
57 | var body: some View {
58 | dots
59 | .opacity(animating ? 1 : 0)
60 | .scaleEffect(animating ? 1 : 0.5)
61 | .rotationEffect(.degrees(rotation))
62 | .onAppear {
63 | fadeIn()
64 | }
65 | .onReceive(timer) { _ in
66 | if animating {
67 | fadeOut()
68 | } else {
69 | fadeIn()
70 | }
71 | }
72 | }
73 |
74 | private func fadeIn() {
75 | withAnimation(.easeInOut(duration: 1.8).delay(delay)) {
76 | rotation += 60
77 | animating = true
78 | }
79 | }
80 |
81 | private func fadeOut() {
82 | withAnimation(.easeInOut(duration: 1.8).delay(1 - delay)) {
83 | rotation += 60
84 | animating = false
85 | }
86 | }
87 |
88 | private var dots: some View {
89 | Canvas { context, size in
90 | let dimensionOffset = size.width/2
91 | let image = context.resolve(Image(systemName: "circle.fill"))
92 | var currentPoint = CGPoint(x: dimensionOffset - image.size.width/2, y: 0)
93 |
94 | for _ in 0...24 {
95 | currentPoint = currentPoint.applying(.init(rotationAngle: Angle.degrees(360/24).radians))
96 | context.draw(image, at: CGPoint(x: currentPoint.x + dimensionOffset, y: currentPoint.y + dimensionOffset))
97 | }
98 | }
99 | .frame(width: 390, height: 390)
100 | .rotationEffect(.degrees(360/48))
101 | }
102 | }
103 |
--------------------------------------------------------------------------------
/appleidanimation.swiftpm/MyApp.swift:
--------------------------------------------------------------------------------
1 | import SwiftUI
2 |
3 | @main
4 | struct MyApp: App {
5 | var body: some Scene {
6 | WindowGroup {
7 | ContentView()
8 | }
9 | }
10 | }
11 |
--------------------------------------------------------------------------------
/appleidanimation.swiftpm/Package.swift:
--------------------------------------------------------------------------------
1 | // swift-tools-version: 5.6
2 |
3 | // WARNING:
4 | // This file is automatically generated.
5 | // Do not edit it by hand because the contents will be replaced.
6 |
7 | import PackageDescription
8 | import AppleProductTypes
9 |
10 | let package = Package(
11 | name: "appleidanimation",
12 | platforms: [
13 | .iOS("15.2")
14 | ],
15 | products: [
16 | .iOSApplication(
17 | name: "appleidanimation",
18 | targets: ["AppModule"],
19 | bundleIdentifier: "com.atrinh.appleidanimation",
20 | teamIdentifier: "6DRH5697SN",
21 | displayVersion: "1.0",
22 | bundleVersion: "1",
23 | appIcon: .placeholder(icon: .leaf),
24 | accentColor: .presetColor(.green),
25 | supportedDeviceFamilies: [
26 | .pad,
27 | .phone
28 | ],
29 | supportedInterfaceOrientations: [
30 | .portrait,
31 | .landscapeRight,
32 | .landscapeLeft,
33 | .portraitUpsideDown(.when(deviceFamilies: [.pad]))
34 | ]
35 | )
36 | ],
37 | targets: [
38 | .executableTarget(
39 | name: "AppModule",
40 | path: "."
41 | )
42 | ]
43 | )
--------------------------------------------------------------------------------
/assets/output.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atrinh0/appleid-animation/fbb9eb6a536a3a881f5ebc0bc1aa3020dbe0b977/assets/output.mp4
--------------------------------------------------------------------------------
/assets/output.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atrinh0/appleid-animation/fbb9eb6a536a3a881f5ebc0bc1aa3020dbe0b977/assets/output.png
--------------------------------------------------------------------------------
/assets/output_square.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atrinh0/appleid-animation/fbb9eb6a536a3a881f5ebc0bc1aa3020dbe0b977/assets/output_square.mov
--------------------------------------------------------------------------------
/assets/source.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atrinh0/appleid-animation/fbb9eb6a536a3a881f5ebc0bc1aa3020dbe0b977/assets/source.mov
--------------------------------------------------------------------------------
/assets/source.png:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/atrinh0/appleid-animation/fbb9eb6a536a3a881f5ebc0bc1aa3020dbe0b977/assets/source.png
--------------------------------------------------------------------------------