首页 > 解决方案 > SwiftUI - 将视图从手势移动到圆周不起作用

问题描述

我正在自动移动圆周上的视图。除此之外,我想用手势移动圆周。自动播放会定期移动,手势会根据手势的速度移动。

存在视图在某个点旋转 360° 的错误。我认为action.gesture的计算方式不同,但我不知道正确答案。

你知道我的计算出了什么问题吗?

import Combine
import SwiftUI
import ComposableArchitecture

fileprivate let timer = Timer.publish(every: 0.01, on: .main, in: .common).autoconnect()
fileprivate let circleWidth: CGFloat = 300

// MARK: - State
struct CircleState: Equatable {
  @BindableState var angle: Double = .zero
  @BindableState var handling: Bool = false
  @BindableState var handleLastAngle: CGFloat = 0
  @BindableState var isTurnRight: Bool = true
  var checkTurnRightValue: Double = .zero
}

// MARK: - Action
enum CircleAction: Equatable {
  case gesture(DragGesture.Value)
  case endGesture
  case auto
}

// MARK: - Reducer
let circleReducer = Reducer<
  CircleState, CircleAction, SignInEnvironment
> { state, action, environment in
  switch action {
  case let .gesture(v):
    var theta = (atan2(v.location.x - circleWidth / 2, circleWidth / 2 - v.location.y)
                 - atan2(v.startLocation.x - circleWidth / 2, circleWidth / 2 - v.startLocation.y)) * 180 / .pi
    if (theta < 0) { theta += 360 }
    state.isTurnRight = state.checkTurnRightValue < theta
    state.checkTurnRightValue = theta
    state.angle = theta + state.handleLastAngle
  case .auto:
    if state.handling { break }
    if state.isTurnRight {
      state.angle += 0.1
    } else {
      state.angle -= 0.1
    }
  case .endGesture:
    state.handling = false
    state.handleLastAngle = state.angle
    break
  }
  return .none
}

struct CircleView: View {
  let store: Store<CircleState, CircleAction>

  init(store: Store<CircleState, CircleAction>) {
    self.store = store
  }
  
  var body: some View {
    WithViewStore(self.store) { viewStore in
      ZStack {
        Circle()
          .strokeBorder(Color.black, lineWidth: 2)
          .frame(width: circleWidth, height: circleWidth)
        
        Circle()
          .foregroundColor(.red)
          .frame(width: 60, height: 60)
          .overlay(
            Text("Hi")
              .rotationEffect(.degrees(-viewStore.angle))
          )
          .offset(x: circleWidth / 2)
          .onReceive(timer) { _ in
            viewStore.send(.auto)
          }
          .animation(.default)
          .rotationEffect(.degrees(viewStore.angle))
      }
      .gesture(
        DragGesture()
          .onChanged { v in viewStore.send(.gesture(v))}
          .onEnded { _ in viewStore.send(.endGesture) }
      )
      .navigationBarHidden(true)
    }
  }
}

struct CircleView_Previews: PreviewProvider {
    static var previews: some View {
      CircleView(store:Store(
        initialState: CircleState(),
        reducer: circleReducer,
        environment: SignInEnvironment(mainQueue: .main, signinClient: SignInClient.signin)
      ))
    }
}

谢谢你。

GIF:https ://i.stack.imgur.com/Kf51D.gif

标签: swiftswiftui

解决方案


推荐阅读