在 SwiftUI 中,Angle 是一个用于表示角度的结构体,可以以弧度或度数的形式定义,常用于旋转视图或实现与角度相关的动画效果。
创建 Angle
SwiftUI 提供了以下几种方式来定义 Angle:
1、通过度数创建:
let angleInDegrees = Angle(degrees: 45)
2、通过弧度创建:
let angleInRadians = Angle(radians: .pi / 4)
3、直接使用静态属性:
let zeroAngle = Angle.zero
在 SwiftUI 中使用 Angle
示例 1:旋转视图
Angle 通常用于视图的旋转。例如,通过 .rotationEffect 实现旋转:
import SwiftUI
struct ContentView: View {
@State private var rotationAngle: Double = 0
var body: some View {
VStack {
Text("Rotate Me!")
.font(.largeTitle)
.rotationEffect(Angle(degrees: rotationAngle))
.padding()
Slider(value: $rotationAngle, in: 0...360, step: 1) {
Text("Rotation")
}
.padding()
}
}
}
示例 2:旋转动画
结合动画,实现视图的动态旋转效果:
import SwiftUI
struct ContentView: View {
@State private var isRotated = false
var body: some View {
VStack {
Image(systemName: "arrow.right")
.resizable()
.frame(width: 100, height: 100)
.rotationEffect(isRotated ? Angle(degrees: 360) : Angle.zero)
.animation(.easeInOut(duration: 2), value: isRotated)
.onTapGesture {
isRotated.toggle()
}
Text("Tap the arrow to rotate")
.padding()
}
}
}
使用 Angle 在圆形布局中排列视图
可以通过计算角度的位置,将子视图排列在圆形布局上:
import SwiftUI
struct ContentView: View {
let items = Array(1...8)
var body: some View {
GeometryReader { geometry in
let radius = min(geometry.size.width, geometry.size.height) / 2
ZStack {
ForEach(0..<items.count, id: \.self) { index in
let angle = Angle(degrees: Double(index) / Double(items.count) * 360)
let xOffset = radius * cos(angle.radians)
let yOffset = radius * sin(angle.radians)
Text("\(items[index])")
.font(.title)
.position(
x: geometry.size.width / 2 + xOffset,
y: geometry.size.height / 2 + yOffset
)
}
}
}
.frame(height: 300)
}
}
角度计算
1、弧度与度数的转换:
SwiftUI 的 Angle 提供了 .degrees 和 .radians 属性,方便相互转换。
let angle = Angle(degrees: 90)
print(angle.radians) // 输出:1.5707963267948966
2、常见角度:
let quarterTurn = Angle.degrees(90)
let halfTurn = Angle.degrees(180)
let fullTurn = Angle.degrees(360)
动态使用示例:结合 Canvas
import SwiftUI
struct ContentView: View {
@State private var angle = Angle.zero
var body: some View {
Canvas { context, size in
let center = CGPoint(x: size.width / 2, y: size.height / 2)
let radius = min(size.width, size.height) / 3
for i in 0..<12 {
let segmentAngle = Angle(degrees: Double(i) * 30) + angle
let x = center.x + radius * cos(segmentAngle.radians)
let y = center.y + radius * sin(segmentAngle.radians)
let circle = Path { path in
path.addEllipse(in: CGRect(x: x - 10, y: y - 10, width: 20, height: 20))
}
context.fill(circle, with: .color(i % 2 == 0 ? .blue : .red))
}
}
.frame(width: 300, height: 300)
.onAppear {
withAnimation(.linear(duration: 5).repeatForever(autoreverses: false)) {
angle = Angle.degrees(360)
}
}
}
}