Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Feature/viewmodel #22

Open
wants to merge 4 commits into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 3 additions & 3 deletions Sources/BigRing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -51,10 +51,10 @@ struct BigRing: View {
// BingRingのPreview用
struct BigRing_Previews: PreviewProvider {
static var previews: some View {
BigRing(bigRingNormalBackgroundColor: .white, bigRingDarkBackgroundColor: .black, bigRingStrokeColor: .primary, bigRingDiameter: 120).environmentObject(OMJoystickViewModel(isOctantLinesVisible: true))
BigRing(bigRingNormalBackgroundColor: .white, bigRingDarkBackgroundColor: .black, bigRingStrokeColor: .primary, bigRingDiameter: 120).environmentObject(OMJoystickViewModel(isOctantLinesVisible: true, smallRingRadius: 30, bigRingRadius: 60))

BigRing(bigRingNormalBackgroundColor: .white, bigRingDarkBackgroundColor: .gray, bigRingStrokeColor: .red, bigRingDiameter: 220).environmentObject(OMJoystickViewModel(isOctantLinesVisible: true))
BigRing(bigRingNormalBackgroundColor: .white, bigRingDarkBackgroundColor: .gray, bigRingStrokeColor: .red, bigRingDiameter: 220).environmentObject(OMJoystickViewModel(isOctantLinesVisible: true, smallRingRadius: 30, bigRingRadius: 60))

BigRing(bigRingNormalBackgroundColor: .white, bigRingDarkBackgroundColor: .black, bigRingStrokeColor: .primary, bigRingDiameter: 120).environmentObject(OMJoystickViewModel(isOctantLinesVisible: false))
BigRing(bigRingNormalBackgroundColor: .white, bigRingDarkBackgroundColor: .black, bigRingStrokeColor: .primary, bigRingDiameter: 120).environmentObject(OMJoystickViewModel(isOctantLinesVisible: false, smallRingRadius: 30, bigRingRadius: 60))
}
}
111 changes: 23 additions & 88 deletions Sources/OMJoyStick.swift
Original file line number Diff line number Diff line change
Expand Up @@ -23,99 +23,34 @@ public struct OMJoystick: View {
var downIcon: Image?

var isDebug = false

var stickPosition: CGPoint {
let stickPositionX = floor(locationX - bigRingRadius)

// 上をY軸プラスにするためにマイナスをかける
var stickPositionY = floor(locationY - bigRingRadius) * -1

// stickPositionYが-0の場合は-を消す
if (stickPositionY == -0) {
stickPositionY = 0
}

return CGPoint(x: stickPositionX, y: stickPositionY)
}

@State private var joyStickState: JoyStickState = .center

public var completionHandler: ((_ joyStickState: JoyStickState, _ stickPosition: CGPoint, _ angle: CGFloat?, _ distanceFromOrigin: Int) -> Void)

var org: CGPoint {
return CGPoint(x: self.bigRingRadius, y: self.bigRingRadius)
}

@State var locationX: CGFloat = 0
@State var locationY: CGFloat = 0

let iconPadding: CGFloat = 10

var smallRingRadius: CGFloat
var bigRingRadius: CGFloat

var smallRingLocationX: CGFloat {
return locationX - bigRingRadius
}

var smallRingLocationY: CGFloat {
return locationY - bigRingRadius
}

var dragGesture: some Gesture {
// minimumDistanceが1以上だとタッチイベントを一切拾わない
DragGesture(minimumDistance: 0)
.onChanged{ value in
let distance = self.org.getDistance(otherPoint: value.location)

let smallRingLimitCenter: CGFloat = self.bigRingRadius - self.smallRingRadius

if (distance <= smallRingLimitCenter) {
// 円の範囲内
self.locationX = value.location.x
self.locationY = value.location.y


} else {
// 円の範囲外の場合は
let radian = self.org.getRadian(pointOnCircle: value.location)

let pointOnCircle = self.org.getPointOnCircle(radius: smallRingLimitCenter, radian: radian)

self.locationX = pointOnCircle.x
self.locationY = pointOnCircle.y
}

// 原点からの距離を取得
let distanceFromOrigin = JoyStickStateCalculator.getDistanceFromOrigin(stickPosition: stickPosition)

viewModel.onChanged(value: value)

let stickPosition = viewModel.stickPosition

// 角度を取得
let angle = JoyStickStateCalculator.getAngle(stickPosition: stickPosition)

if viewModel.isOctantLinesVisible {
// 八等分の場合
self.joyStickState = JoyStickStateCalculator.getJoyStickStateOctant(angle: angle,
stength: distanceFromOrigin
)
} else {
// 四等分の場合
self.joyStickState = JoyStickStateCalculator.getJoyStickStateQuadrant(angle: angle,
distanceFromOrigin: distanceFromOrigin
)
}
let distanceFromOrigin = JoyStickStateCalculator.getDistanceFromOrigin(stickPosition: stickPosition)

self.completionHandler(self.joyStickState, self.stickPosition, angle, distanceFromOrigin)
self.completionHandler(viewModel.joyStickState, viewModel.stickPosition, angle, distanceFromOrigin)
}
.onEnded{ value in

self.locationX = self.bigRingRadius
self.locationY = self.bigRingRadius
viewModel.onEnded()

self.joyStickState = .center
let angle: CGFloat? = nil
let discanceFromOrigin = 0
let stickPosition = viewModel.stickPosition

self.completionHandler(self.joyStickState, self.stickPosition, angle, discanceFromOrigin)
self.completionHandler(viewModel.joyStickState, stickPosition, angle, discanceFromOrigin)
}
}

Expand All @@ -138,13 +73,10 @@ public struct OMJoystick: View {
self.downIcon = iconSetting.downIcon
}

self.smallRingRadius = smallRingRadius
self.bigRingRadius = bigRingRadius

self.completionHandler = completionHandler

// ViewModelの初期化
self.viewModel = OMJoystickViewModel(isOctantLinesVisible: isOctantLinesVisible)
self.viewModel = OMJoystickViewModel(isOctantLinesVisible: isOctantLinesVisible, smallRingRadius: smallRingRadius, bigRingRadius: bigRingRadius)
}

public var body: some View {
Expand All @@ -162,9 +94,9 @@ public struct OMJoystick: View {
BigRing(
bigRingNormalBackgroundColor: bigRingNormalBackgroundColor, bigRingDarkBackgroundColor: bigRingDarkBackgroundColor,
bigRingStrokeColor: bigRingStrokeColor,
bigRingDiameter: bigRingRadius*2).environmentObject(viewModel).gesture(dragGesture)
bigRingDiameter: viewModel.bigRingRadius*2).environmentObject(viewModel).gesture(dragGesture)

SmallRing(smallRingDiameter: smallRingRadius*2, subRingColor: subRingColor).offset(x: smallRingLocationX, y: smallRingLocationY).environmentObject(viewModel).allowsHitTesting(false)
SmallRing(smallRingDiameter: viewModel.smallRingRadius*2, subRingColor: subRingColor).offset(x: viewModel.smallRingLocationX, y: viewModel.smallRingLocationY).environmentObject(viewModel).allowsHitTesting(false)
}

rightIcon?.renderingMode(.template)
Expand All @@ -176,29 +108,32 @@ public struct OMJoystick: View {

if isDebug {
VStack(spacing: 5) {
HStack() {
Text("LocationXY:").font(.body)
Text(viewModel.locationX.text()).font(.body)
Text(":").font(.body)
Text(viewModel.locationY.text()).font(.body)
}
HStack() {
Text("StickPosition:").font(.body)
Text(stickPosition.x.text()).font(.body)
Text(viewModel.stickPosition.x.text()).font(.body)
Text(":").font(.body)
Text(stickPosition.y.text()).font(.body)
Text(viewModel.stickPosition.y.text()).font(.body)
}
HStack {
Text("JoyStickState:").font(.body)
Text(joyStickState.rawValue).font(.body)
Text(viewModel.joyStickState.rawValue).font(.body)
}
HStack {
Text("DistanceFromOrigin:").font(.body)
Text(String(JoyStickStateCalculator.getDistanceFromOrigin(stickPosition: stickPosition))).font(.body)
Text(String(JoyStickStateCalculator.getDistanceFromOrigin(stickPosition: viewModel.stickPosition))).font(.body)
}
HStack {
Text("Angle:").font(.body)
Text(JoyStickStateCalculator.getAngle(stickPosition: stickPosition).text()).font(.body)
Text(JoyStickStateCalculator.getAngle(stickPosition: viewModel.stickPosition).text()).font(.body)
}
}
}
}.onAppear(){
self.locationX = self.bigRingRadius
self.locationY = self.bigRingRadius
}.padding(40)
}
}
Expand Down
2 changes: 0 additions & 2 deletions Sources/SmallRing.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,6 @@ import SwiftUI

/// Small ring
struct SmallRing: View {
@EnvironmentObject var viewModel: OMJoystickViewModel

var smallRingDiameter: CGFloat
var subRingColor: Color

Expand Down
91 changes: 90 additions & 1 deletion Sources/ViewModel/OMJoystickViewModel.swift
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,96 @@ class OMJoystickViewModel: ObservableObject {
// 8等分のラインを表示するか制御する
public var isOctantLinesVisible: Bool

public init(isOctantLinesVisible: Bool = false) {
public init(isOctantLinesVisible: Bool, smallRingRadius: CGFloat, bigRingRadius: CGFloat) {
self.isOctantLinesVisible = isOctantLinesVisible
self.smallRingRadius = smallRingRadius
self.bigRingRadius = bigRingRadius

self.locationX = bigRingRadius
self.locationY = bigRingRadius
self.joyStickState = .center
}

@Published public var joyStickState: JoyStickState = .center

var smallRingRadius: CGFloat
var bigRingRadius: CGFloat

@Published var locationX: CGFloat = 0
@Published var locationY: CGFloat = 0

var smallRingLocationX: CGFloat {
return locationX - bigRingRadius
}

var smallRingLocationY: CGFloat {
return locationY - bigRingRadius
}

var stickPosition: CGPoint {
let stickPositionX = floor(locationX - bigRingRadius)

// 上をY軸プラスにするためにマイナスをかける
var stickPositionY = floor(locationY - bigRingRadius) * -1

// stickPositionYが-0の場合は-を消す
if (stickPositionY == -0) {
stickPositionY = 0
}

return CGPoint(x: stickPositionX, y: stickPositionY)
}

var org: CGPoint {
return CGPoint(x: self.bigRingRadius, y: self.bigRingRadius)
}

// DragChangeでonChangedした時に実行する処理
func onChanged(value: DragGesture.Value) {
let distance = self.org.getDistance(otherPoint: value.location)

let smallRingLimitCenter: CGFloat = self.bigRingRadius - self.smallRingRadius

if (distance <= smallRingLimitCenter) {
// 円の範囲内
self.locationX = value.location.x
self.locationY = value.location.y


} else {
// 円の範囲外の場合は
let radian = self.org.getRadian(pointOnCircle: value.location)

let pointOnCircle = self.org.getPointOnCircle(radius: smallRingLimitCenter, radian: radian)

self.locationX = pointOnCircle.x
self.locationY = pointOnCircle.y
}

// 原点からの距離を取得
let distanceFromOrigin = JoyStickStateCalculator.getDistanceFromOrigin(stickPosition: stickPosition)

// 角度を取得
let angle = JoyStickStateCalculator.getAngle(stickPosition: stickPosition)

if isOctantLinesVisible {
// 八等分の場合
self.joyStickState = JoyStickStateCalculator.getJoyStickStateOctant(angle: angle,
stength: distanceFromOrigin
)
} else {
// 四等分の場合
self.joyStickState = JoyStickStateCalculator.getJoyStickStateQuadrant(angle: angle,
distanceFromOrigin: distanceFromOrigin
)
}
}

// DragChangeでonEndedした時に実行する処理
func onEnded() {
self.locationX = self.bigRingRadius
self.locationY = self.bigRingRadius

self.joyStickState = .center
}
}