macOS アプリで キーボードとの組み合わて動くマウス操作の作り方を説明します
Sponsor Link
環境&対象
以下の環境で動作確認を行なっています。
- macOS Big Sur 11.2.2
- Xcode 12.4
キーボードと組み合わせて動くマウス操作
macOS アプリでは、キーボードと組み合わせることのできるマウス操作があります。
例えば、Finder 上で、ファイルをドラッグすると移動になりますが、⌘ キーを押しながらドラッグすると、(移動ではなく)コピーになります。
SwiftUI でこのような振る舞いをどのように実装するのかを説明します。
SwiftUI でのマウス操作の実装
.gesture を使って、実装していくことになります。
例えばテキストをドラッグして移動するような操作は、以下のような実装となります。
DragGesture Example
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 |
struct ContentView: View { @State private var textOffset: CGSize = CGSize.zero @State var dragStartPosition: CGPoint = CGPoint.zero @State var isDragging:Bool = false var body: some View { ZStack { Color.white.frame(width: 800, height: 800) Text("Hello, World!") .background(Color.white) .offset(textOffset) // (1) .gesture(DragGesture() // (2) .onChanged { gesture in if self.isDragging == false { self.dragStartPosition = CGPoint(x: self.textOffset.width, y: self.textOffset.height) self.isDragging = true } self.textOffset = CGSize(width: gesture.translation.width + self.dragStartPosition.x, height: gesture.translation.height + self.dragStartPosition.y) } // (3) .onEnded { gesture in self.isDragging = false }) } } } |
コード解説
- .gesture modifier を使って、ビューにマウス操作を定義することができます。ここでは、DragGesture を使用してドラッグ操作を定義しています。
- ドラッグ中には、onChanged が呼ばれます。ここでは .offset と組み合わせて、テキストの表示位置を移動させています。
- ドラッグ終了時には、onEnded が呼ばれます。
shift キーと組み合わせる
グラフィック系のアプリケーションで、shift キーを押すと、グリッドに吸着するという操作になるアプリケーションをみたことがあります。
ここでは、100 px ごとにグリッドがあるという想定で、shift キーを押されているときは、そのグリッド上にしか移動できない操作を実装してみます。
※ shift が押されていなければ、自由に移動できます。
DragGesture with shift
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
struct ContentView: View { @State private var textOffset: CGSize = CGSize.zero @State var dragStartPosition: CGPoint = CGPoint.zero @State var isDragging:Bool = false var body: some View { ZStack { Color.white.frame(width: 800, height: 800) Text("Hello, World!") .background(Color.white) .offset(textOffset) // (1), (2) .gesture(DragGesture().modifiers(.shift) .onChanged { gesture in if self.isDragging == false { self.dragStartPosition = CGPoint(x: self.textOffset.width, y: self.textOffset.height) self.isDragging = true } let newOffset = CGSize(width: gesture.translation.width + self.dragStartPosition.x, height: gesture.translation.height + self.dragStartPosition.y) // (3) self.textOffset = CGSize(width: CGFloat(Int(newOffset.width/100) * 100), height: CGFloat(Int(newOffset.height/100)*100)) } .onEnded { gesture in self.isDragging = false }) // (2') .gesture(DragGesture() .onChanged { gesture in if self.isDragging == false { self.dragStartPosition = CGPoint(x: self.textOffset.width, y: self.textOffset.height) self.isDragging = true } self.textOffset = CGSize(width: gesture.translation.width + self.dragStartPosition.x, height: gesture.translation.height + self.dragStartPosition.y) } .onEnded { gesture in self.isDragging = false }) } } } |
コード解説
- .modifier を指定することで、DragGesture 時の修飾キーを指定することができます
- 同じ Gesture (ここでは DragGesture)を指定するときは、指定の順番に気をつける必要があります。最初にマッチした Gesture になってしまうので、shift アリ/ナシ で分ける時には、shift アリを最初に記述する必要があります。記述の順番を逆にすると、常に shift ナシ が動作します。
- 100 px のグリッド上に来るように計算しています。
注意点
上記の指定方法は、Gesture 開始時に条件がマッチしている必要があります。上記の例であれば、ドラッグ開始後に、shift キーを押下する / 離す ということをしても、動作中の Gesture が切り替わるわけではありません。
Gesture 中のキー切り替えで振る舞いが変わる Gesture を作るためには、工夫が必要となります。
まとめ:キーボードと組み合わせたマウス操作
キーボードと組み合わせたマウス操作
- Gesture に、.modifier を指定することで、キーボードと組み合わせて特定の Gesture を開始させることができる
- 条件を満たす最初の Gesture が開始されるため、記述の順番に気をつける必要がある
- 注意:Gesture 途中で、キーボードを操作しても、Gesture は切り替わらない
説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。
Sponsor Link