先看一下今日成果
試著把操作面板調整小一點
PanelView.swift
struct PanelView: View {
@Binding var lightSettings: LightSettings
var body: some View {
HStack {
RotationPanel(rotationOffset: $lightSettings.rotationOffset)
.frame(width: 120, height: 120)
VStack {
Slider(value: $lightSettings.circleSize, in: 20...80)
Text("光圈: \(Int(lightSettings.circleSize))")
Slider(value: $lightSettings.brightness, in: 0.5...1)
Text("亮度: \(Int(lightSettings.brightness*100))")
ColorPicker("顏色", selection: $lightSettings.color)
}
VStack {
PositionPanel(offset: $lightSettings.offset)
.frame(width: 120, height: 120)
Button(action: {
lightSettings.offset = .zero
}) {
Image(systemName: "camera.metering.center.weighted")
}
.padding()
}
}
.padding()
}
}
旋轉面板加一個state,在DragGesture()手勢放開後自動歸零。
struct RotationPanel: View {
@Binding var rotationOffset: CGSize
@State private var lastOffset: CGSize = .zero
@State private var isLock: Bool = false
var body: some View {
VStack {
GeometryReader { geometry in
ZStack {
Circle()
.stroke(Color.gray, lineWidth: 2)
.frame(width: 120, height: 120)
Circle()
.fill(Color.blue)
.frame(width: 20, height: 20)
.offset(rotationOffset)
.gesture(
DragGesture()
.onChanged { value in
let radius = 60.0 // 圓形的半徑
var newX = value.translation.width + lastOffset.width
var newY = value.translation.height + lastOffset.height
let distance = sqrt(newX * newX + newY * newY)
if distance > radius {
let angle = Double(atan2(newY, newX))
newX = radius * cos(angle)
newY = radius * sin(angle)
}
rotationOffset = CGSize(width: newX, height: newY)
}
.onEnded { _ in
if isLock {
lastOffset = rotationOffset
} else {
rotationOffset = .zero
}
}
)
}
}
Button(action: {
isLock.toggle()
}) {
Text(isLock ? "解鎖" : "鎖定")
}.offset(x: 0, y: 40)
}
}
}
發現一個新問題,因為PositionPanel為正方形,雖然縮小PanelView讓LightZone空間變大,卻無法運用到所有空間。明天週末有多一點時間嘗試毛玻璃模糊效果與各種版型的Layout。