LoginSignup
5
4

More than 3 years have passed since last update.

【SwiftUI】ビューをジェスチャーで回転させ、90°ずつスナップを効かせる方法

Last updated at Posted at 2020-05-23

【SwiftUI】ビューをジェスチャーで回転させ、90°ずつスナップを効かせる方法

こんにちは、たいちです(@taichi_swift_)

たかし「お絵かきアプリとかでよくある、ビューを回転させて90°づつピタって止めるやつ、どうやって実装するんだろ...」

こちらのお悩みを解決します。

ビューを回転させる方法

まずは、基本のビューを回転させる方法です。
SwiftUIでは、
.rotationEffect(_ angle: Angle, anchor: UnitPoint = .center)
というmodifierを使用します。

実際に使うときには、
.rotationEffect(Angle(degrees: 90))
みたいに使うわけですね。

IMG_1985 2.jpg

Text("RotationEffect")
    .rotationEffect(Angle(degrees: 90))

ビューをジェスチャーで回転させる方法

続いて、ユーザーが指を使ってビューを回転させる方法です。
.gesture()
を使います。

まずは、角度を格納する変数を2つ用意します。

@State var angle = Angle(degrees: 0.0)
@State private var oldAngle = Angle(degrees: 0.0)

そして、ジェスチャーを用意します

var rotation: some Gesture {
    RotationGesture()
        .onChanged { angle in
            self.angle = self.oldAngle + angle                
        }
        .onEnded { angle in
            self.oldAngle = self.angle
        }
    }

そんでこのジェスチャーをテキトーなビューにがっちゃんこします。
.rotationEffect(self.angle)
.gesture(rotation)

RoundedRectangle(cornerRadius: 20)
    .frame(width: 400, height: 300)
    .rotationEffect(self.angle)
    .gesture(rotation)

すると、二本指で自由に操れるビューができました。
IMG_1986.jpg

ビューを回転させ、スナップさせる方法

やっときました。本題です。

先ほど定義した、rotationという名前のgestureにちょこっと細工を加えてあげます。

var rotation: some Gesture {
    RotationGesture()
        .onChanged { angle in
            self.angle = self.oldAngle + angle
            if abs(Int(self.angle.degrees) % 90) < 5 {
                self.angle = Angle(degrees: Double(Int(self.angle.degrees) - Int(self.angle.degrees) % 90))
            }
        }
        .onEnded { angle in
            self.oldAngle = self.angle
        }
}

完成です。

struct ContentView: View {
    @State var angle = Angle(degrees: 0.0)
    @State private var oldAngle = Angle(degrees: 0.0)

    var rotation: some Gesture {
        RotationGesture()
            .onChanged { angle in
                self.angle = self.oldAngle + angle
                if abs(Int(self.angle.degrees) % 90) < 5 {
                    self.angle = Angle(degrees: Double(Int(self.angle.degrees) - Int(self.angle.degrees) % 90))
                }                
            }
            .onEnded { angle in
                self.oldAngle = self.angle
            }
        }
        var body: some View {
        RoundedRectangle(cornerRadius: 20)
            .frame(width: 400, height: 300)
            .rotationEffect(self.angle)
            .gesture(rotation)        
    }
}
5
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
4