Skip to content

Commit 395114d

Browse files
committed
Add clock animation demo, support Chinese and English localization
1 parent b273468 commit 395114d

File tree

20 files changed

+1138
-0
lines changed

20 files changed

+1138
-0
lines changed

Clock/Clock.xcodeproj/project.pbxproj

+399
Large diffs are not rendered by default.

Clock/Clock.xcodeproj/project.xcworkspace/contents.xcworkspacedata

+7
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
<?xml version="1.0" encoding="UTF-8"?>
2+
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
3+
<plist version="1.0">
4+
<dict>
5+
<key>IDEDidComputeMac32BitWarning</key>
6+
<true/>
7+
</dict>
8+
</plist>
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"colors" : [
3+
{
4+
"idiom" : "universal"
5+
}
6+
],
7+
"info" : {
8+
"author" : "xcode",
9+
"version" : 1
10+
}
11+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
{
2+
"images" : [
3+
{
4+
"idiom" : "iphone",
5+
"scale" : "2x",
6+
"size" : "20x20"
7+
},
8+
{
9+
"idiom" : "iphone",
10+
"scale" : "3x",
11+
"size" : "20x20"
12+
},
13+
{
14+
"idiom" : "iphone",
15+
"scale" : "2x",
16+
"size" : "29x29"
17+
},
18+
{
19+
"idiom" : "iphone",
20+
"scale" : "3x",
21+
"size" : "29x29"
22+
},
23+
{
24+
"idiom" : "iphone",
25+
"scale" : "2x",
26+
"size" : "40x40"
27+
},
28+
{
29+
"idiom" : "iphone",
30+
"scale" : "3x",
31+
"size" : "40x40"
32+
},
33+
{
34+
"idiom" : "iphone",
35+
"scale" : "2x",
36+
"size" : "60x60"
37+
},
38+
{
39+
"idiom" : "iphone",
40+
"scale" : "3x",
41+
"size" : "60x60"
42+
},
43+
{
44+
"idiom" : "ipad",
45+
"scale" : "1x",
46+
"size" : "20x20"
47+
},
48+
{
49+
"idiom" : "ipad",
50+
"scale" : "2x",
51+
"size" : "20x20"
52+
},
53+
{
54+
"idiom" : "ipad",
55+
"scale" : "1x",
56+
"size" : "29x29"
57+
},
58+
{
59+
"idiom" : "ipad",
60+
"scale" : "2x",
61+
"size" : "29x29"
62+
},
63+
{
64+
"idiom" : "ipad",
65+
"scale" : "1x",
66+
"size" : "40x40"
67+
},
68+
{
69+
"idiom" : "ipad",
70+
"scale" : "2x",
71+
"size" : "40x40"
72+
},
73+
{
74+
"idiom" : "ipad",
75+
"scale" : "1x",
76+
"size" : "76x76"
77+
},
78+
{
79+
"idiom" : "ipad",
80+
"scale" : "2x",
81+
"size" : "76x76"
82+
},
83+
{
84+
"idiom" : "ipad",
85+
"scale" : "2x",
86+
"size" : "83.5x83.5"
87+
},
88+
{
89+
"idiom" : "ios-marketing",
90+
"scale" : "1x",
91+
"size" : "1024x1024"
92+
}
93+
],
94+
"info" : {
95+
"author" : "xcode",
96+
"version" : 1
97+
}
98+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
{
2+
"info" : {
3+
"author" : "xcode",
4+
"version" : 1
5+
}
6+
}

Clock/Clock/ClockApp.swift

+17
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//
2+
// ClockApp.swift
3+
// Clock
4+
//
5+
// Created by Liu Chuan on 2020/11/03.
6+
//
7+
8+
import SwiftUI
9+
10+
@main
11+
struct ClockApp: App {
12+
var body: some Scene {
13+
WindowGroup {
14+
ContentView()
15+
}
16+
}
17+
}

Clock/Clock/ClockDialView.swift

+173
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,173 @@
1+
//
2+
// ClockDialView.swift
3+
// Clock
4+
//
5+
// Created by Liu Chuan on 2020/11/03.
6+
//
7+
8+
import SwiftUI
9+
10+
11+
/// 时钟表盘视图
12+
struct ClockDialView: View {
13+
14+
/*
15+
90度:15分钟,5分钟= 90/3,1分钟= 90/3/5 = 6°
16+
*/
17+
18+
/// 当前时间
19+
@Binding var currentTime: Time
20+
21+
/// 是否为暗黑模式
22+
@Binding var isDark: Bool
23+
24+
/// 秒针的颜色(默认:Color.primary)
25+
@State var secondColor: Color = Color.red
26+
27+
/// 表盘颜色(默认为白色)
28+
@State var dialColor: Color = Color("Color")
29+
30+
/// 秒针的高度
31+
private let secHeight: CGFloat = screenW / 2 - 20
32+
33+
34+
var body: some View {
35+
36+
ZStack {
37+
Circle()
38+
.fill(dialColor)
39+
.frame(width: screenW - 50, height: screenW - 50)
40+
41+
Text("ROLEX")
42+
.foregroundColor(Color.primary)
43+
.font(.system(size: 25))
44+
.offset(x: 0, y: -90)
45+
46+
// 工作日
47+
Text("\(getWeekdayWithNumber()) \(getday())")
48+
.fontWeight(.bold)
49+
.background(isDark ? Color.white : Color.black)
50+
.foregroundColor(isDark ? Color.black : Color.white)
51+
.offset(x: 70)
52+
53+
// 表盘上的刻度
54+
ForEach(0 ..< 60, id: \.self) { i in
55+
Rectangle()
56+
.fill(Color.primary)
57+
// 每小时:60 / 12 = 5
58+
// (i % 5) == 0 : 小时刻度
59+
.frame(width: (i % 5) == 0 ? 15 : 5, height: (i % 5) == 0 ? 15 : 5)
60+
.cornerRadius(i % 5 == 0 ? 15 / 2 : 0)
61+
.offset(y: (screenW - 110) / 2)
62+
.rotationEffect(.init(degrees: Double(i) * 6))
63+
64+
// 数字
65+
if i % 5 == 0 {
66+
HourTexts(index: i, marginRatio: 3 / 8)
67+
}
68+
}
69+
70+
// Hour
71+
Rectangle()
72+
.fill(Color.primary)
73+
.frame(width: 6.5, height: secHeight / 3)
74+
.offset(y: -secHeight / 3 / 2)
75+
.rotationEffect(.init(degrees: (Double(currentTime.hour) + (Double(currentTime.min) / 60)) * 30))
76+
77+
// Min
78+
Rectangle()
79+
.fill(Color.primary)
80+
.frame(width: 6, height: secHeight / 2)
81+
.offset(y: -secHeight / 2 / 2)
82+
.rotationEffect(.init(degrees: Double(currentTime.min) * 6))
83+
84+
// Sec
85+
Rectangle()
86+
.fill(secondColor)
87+
.frame(width: 2, height: secHeight)
88+
.offset(x: 0, y: -50)
89+
90+
// 秒针上的2个圆
91+
.overlay(
92+
Circle()
93+
.foregroundColor(secondColor)
94+
.frame(width: 12, height: 12)
95+
.offset(x: 0, y: -100)
96+
)
97+
.overlay(
98+
Circle()
99+
.foregroundColor(secondColor)
100+
.frame(width: 10, height: 10)
101+
.offset(x: 0, y: secHeight / 2 - 50)
102+
)
103+
// 旋转1分钟的6度
104+
.rotationEffect(.init(degrees: Double(currentTime.sec) * 6))
105+
106+
// 中心圆
107+
Circle()
108+
.fill(Color.primary)
109+
.frame(width: 15, height: 15)
110+
}
111+
}
112+
}
113+
114+
// MARK: - Get date method
115+
extension ClockDialView {
116+
117+
/// 根据数字获取工作日
118+
/// - Parameter number: 数字
119+
func getWeekdayWithNumber() -> String {
120+
121+
/*
122+
星期一,Mon.(全称Monday)
123+
星期二,Tues.(全称Tuesday)
124+
星期三,Wed.(全称Wednesday)
125+
星期四,Thur.(全称Thursday)
126+
星期五,Fri.(全称Friday)
127+
星期六,Sat.(全程Saturday)
128+
星期日 Sun.(全称Sunday)
129+
*/
130+
131+
/// 创建日历对象
132+
var calender = Calendar.current
133+
//默认情况下,日历未设置语言环境。
134+
//如果您希望收到本地化的答案,请务必首先将locale属性设置为。Locale.autoupdatingCurrent
135+
calender.locale = Locale.autoupdatingCurrent
136+
137+
/// 返回日期的周
138+
let number = calender.component(.weekday, from: Date())
139+
// 使用本地化字符串
140+
switch number {
141+
case 1:
142+
return NSLocalizedString("Sun", comment: "")
143+
case 2:
144+
return NSLocalizedString("Mon", comment: "")
145+
case 3:
146+
return NSLocalizedString("Tues", comment: "")
147+
case 4:
148+
return NSLocalizedString("Wed", comment: "")
149+
case 5:
150+
return NSLocalizedString("Thur", comment: "")
151+
case 6:
152+
return NSLocalizedString("Fri", comment: "")
153+
case 7:
154+
return NSLocalizedString("Sat", comment: "")
155+
default:
156+
return ""
157+
}
158+
}
159+
160+
/// 获取当前几日
161+
func getday() -> String {
162+
/// 创建日历对象
163+
var calender = Calendar.current
164+
//默认情况下,日历未设置语言环境。
165+
//如果您希望收到本地化的答案,请务必首先将locale属性设置为。Locale.autoupdatingCurrent
166+
calender.locale = Locale.autoupdatingCurrent
167+
// 获取多少号
168+
let day = calender.component(.day, from: Date())
169+
return "\(day)"
170+
}
171+
172+
}
173+

Clock/Clock/ClockView.swift

+68
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
//
2+
// ClockView.swift
3+
// Clock
4+
//
5+
// Created by Liu Chuan on 2020/11/03.
6+
//
7+
8+
import SwiftUI
9+
10+
/// 时钟视图
11+
struct ClockView: View {
12+
13+
/// 是否为暗黑模式
14+
@Binding var isDark : Bool
15+
16+
/// 当前时间
17+
@State var currentTime = Time(sec: 0, min: 0, hour: 0)
18+
19+
/// 接受者
20+
@State var receiver = Timer.publish(every: 1, on: .current, in: .default).autoconnect()
21+
22+
/// 秒针的颜色(默认:Color.primary)
23+
@State var secondColor: Color = Color.primary
24+
25+
/// 表盘主题颜色
26+
@State var dialThemeColor: Color = Color("Color")
27+
28+
/// 是否为 12小时制
29+
@State var is12HourClock: Bool = false
30+
31+
32+
var body: some View {
33+
VStack {
34+
TopView(isDark: $isDark)
35+
36+
Spacer(minLength: 0)
37+
38+
ClockDialView(currentTime: $currentTime, isDark: $isDark, secondColor: secondColor, dialColor: dialThemeColor)
39+
.frame(width: screenW, height: screenW)
40+
41+
TimeZoneView(is12h: $is12HourClock)
42+
43+
Spacer(minLength: 0)
44+
}
45+
.onAppear(perform: {
46+
let calender = Calendar.current
47+
let min = calender.component(.minute, from: Date())
48+
let sec = calender.component(.second, from: Date())
49+
let hour = calender.component(.hour, from: Date())
50+
51+
withAnimation(Animation.linear(duration: 0.01)) {
52+
self.currentTime = Time(sec: sec, min: min, hour: hour)
53+
}
54+
})
55+
.onReceive(receiver) { (_) in
56+
/// 创建日历对象
57+
let calender = Calendar.current
58+
// component: 返回日期的组成部分的值
59+
let min = calender.component(.minute, from: Date())
60+
let sec = calender.component(.second, from: Date())
61+
let hour = calender.component(.hour, from: Date())
62+
63+
withAnimation(Animation.linear(duration: 0.01)) {
64+
self.currentTime = Time(sec: sec, min: min, hour: hour)
65+
}
66+
}
67+
}
68+
}

0 commit comments

Comments
 (0)