iT邦幫忙

2024 iThome 鐵人賽

DAY 2
0
Mobile Development

從概念發想上架一支SwiftUI app系列 第 2

基礎部分 - SwiftUI做中學

  • 分享至 

  • xImage
  •  

今天運用了

  • 基本元件(Text, Slider, ColorPicker)
  • 元件排列(ZStack, VStack)
  • 手勢(DragGesture)
  • Property wrapper(State, Binding)

ContentView

構成兩個主區塊,以及宣告幾個變數加上@State

struct ContentView: View {
    @State private var circleSize: CGFloat = 20
    @State private var brightness: Double = 1.0
    @State private var circleColor: Color = .white
    @State private var offset: CGSize = .zero

    var body: some View {
        VStack {
            LightZone(circleSize: circleSize, brightness: brightness, color: circleColor, offset: $offset)
                .frame(maxWidth: .infinity)
            PanelView(circleSize: $circleSize, brightness: $brightness, color: $circleColor, offset: $offset)
                .frame(maxWidth: .infinity, maxHeight: .infinity, alignment: .bottom)
        }
    }
}

LightZone

變數offset加上@Binding

struct LightZone: View {
    let circleSize: CGFloat
    let brightness: Double
    let color: Color
    
    let scale = UIScreen.main.bounds.width/200.0
    
    @Binding var offset: CGSize

    var body: some View {
        ZStack {
            Color.black
                .ignoresSafeArea()
            Circle()
                .fill(color.opacity(brightness))
                .frame(width: circleSize, height: circleSize)
                .offset(CGSize(width: offset.width*scale, height: offset.height*scale))
        }
    }
}

PanelView

struct PanelView: View {
    @Binding var circleSize: CGFloat
    @Binding var brightness: Double
    @Binding var color: Color
    @Binding var offset: CGSize

    var body: some View {
        VStack {
            Slider(value: $circleSize, in: 10...50)
            Text("光圈大小: \(Int(circleSize))")
            Slider(value: $brightness, in: 0.5...1)
            Text("亮度: \(brightness, format: .percent)")
            ColorPicker("顏色選擇", selection: $color)
            PositionPanel(offset: $offset)
                .frame(width: 200, height: 200)
        }
        .padding()
    }
}

PositionPanel
今天花了較多時間在PositionPanel,SwiftUI的語言很簡潔。
還有一個小問題要調整,MovableCircle應該要限制在區域內。

struct PositionPanel: View {
    @Binding var offset: CGSize
    
    var body: some View {
            ZStack {
                Rectangle()
                    .fill(Color.gray)
                
                MovableCircle()
                    .offset(offset)
                    .gesture(
                        DragGesture()
                            .onChanged { value in
                                let maxOffset = 200.0
                                
                                // 放大 offset 的值
                                let newX = max(-maxOffset, min(value.translation.width, maxOffset))
                                let newY = max(-maxOffset, min(value.translation.height, maxOffset))
                                offset = CGSize(width: newX, height: newY)
                            }
                    )
            }
        }
}

MovableCircle

struct MovableCircle: View {
    var body: some View {
        Circle()
            .fill(Color.white)
            .frame(width: 20, height: 20)
    }
}

明天會增加一個手勢控制區域,用來模擬光源角度變化。
查詢幾個語法的效果,可能會先試試LinearGradient搭配模糊效果。
手勢區要如何定義也是個好問題。
大家可以思考看看有什麼做法。
day2截稿前不知道怎麼上圖片, day3補上


上一篇
我有一個好點子, 然後呢
下一篇
基礎部分 - 旋轉面板
系列文
從概念發想上架一支SwiftUI app30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言