Sponsor Link
目次
ゴール:Imageの上にTextを表示して、そのTextをマウスドラッグで移動させたい
以下のようなステップで作っていきます。
・イメージを表示
・テキストをイメージに重ねて表示
・テキストをドラッグ可能に
・ドラッグされた時にテキストを移動
Step0: Imageを表示
表示する写真
例えば、このような写真を表示する。
Assets.xcassetsに登録
表示するためには、プロジェクトのリソースに登録しておくと簡単にできます。
ということで、Assets.xcassetsにドラッグアンドドロップして登録します。
使ったファイルは、JPGファイルなので、ファイル名は、View.jpgです。
Imageビューの引数にファイルを指定して表示するようにします。
struct ContentView: View {
var body: some View {
ZStack{
Image("View")
.resizable()
.scaledToFit()
}
}
}
こんな感じになります。
Step1: ImageとTextを重ねて表示
目標は、Image上にTextを配置して、そのTextをマウスドラッグで動かすことなので、そのためのTextを配置します。
確認しやすいように、背景を白にしてTextを配置します。
struct ContentView: View {
var body: some View {
ZStack{
Image("View")
.resizable()
.scaledToFit()
Text("Hello, World!")
.background(Color.white)
}
}
}
Hello World!がイメージ上に表示されているのが確認できます。
Step2: Textのドラッグ対応
SwiftUIでは、.gesture modifierで受けます。
全般については、ここを。
今回は、ドラッグでの操作を行いたいので、使用するクラスは、DragGestureになります。DragGestureについては、こちらを。
ざっくりいうと、ドラッグ中とドラッグ終了時に指定Closureが実行されます。
まずは、どんな感じになるか確認するために、簡単なprint文を埋め込んだコードにしてみます。
struct ContentView: View {
var body: some View {
ZStack{
Image("View")
.resizable()
.scaledToFit()
Text("Hello, World!")
.background(Color.white)
.gesture(DragGesture() //追加部分はじまり
.onChanged { gesture in
print("\(gesture.translation)")
}
.onEnded { gesture in
print("onEnded")
}) // 追加部分おわり
}
}
}
ここでは、ドラッグ中の移動距離(.translation)をprintしています。
アプリとして動かしてみると、以下のようにコンソールに表示されることを確認できるかと思います。
(13.296875, 8.17578125) (18.66015625, 10.85546875) (24.8671875, 13.67578125) (29.44140625, 16.21484375) (34.015625, 19.265625) (37.859375, 21.66796875) (43.22265625, 24.8828125) (47.2890625, 28.44140625) (51.86328125, 31.4921875) onEnded
ちなみに、上下左右に動かしてみると表示される+/ーが切り替わっていきますので、X軸Y軸のどちら側がプラスでどちら側がマイナスかがわかります。普通の数学でならうものと比較するとY軸方向が逆(上方向がマイナス、下方向がプラス)になっているのがわかるかと思います。
Step3: Textのoffset表示
テキストをどうやって動かすかですが、Textの表示位置をoffsetさせることで実現することにします。.offset modiferというものが用意されています。どのような意味を持つか使ってみましょう。
@State修飾子がついた変数として、textOffsetを定義し、その値を.offset modifierでテキストに適用しています。
struct ContentView: View {
@State private var textOffset: CGSize = CGSize(width: 200, height: -150)
var body: some View {
ZStack{
Image("View")
.resizable()
.scaledToFit()
Text("Hello, World!")
.background(Color.white)
.offset(textOffset)
.gesture(DragGesture()
.onChanged { gesture in
print("\(gesture.translation)")
}
.onEnded { gesture in
print("onEnded")
})
}
}
}
以下のようになり、offset指定することでTextの位置が動かされていることがわかります。
Step4: offsetを使ってドラッグで移動
このtextOffset変数とDragGesture時に取れるtranslationを紐づけることで、Textを移動できそうです。
struct ContentView: View {
@State private var textOffset: CGSize = CGSize.zero // - 注意!
var body: some View {
ZStack{
Image("View")
.resizable()
.scaledToFit()
Text("Hello, World!")
.background(Color.white)
.offset(textOffset)
.gesture(DragGesture()
.onChanged { gesture in
self.textOffset = gesture.translation
}
.onEnded { gesture in
print("onEnded")
})
}
}
}
Step5: まとめ
Image上に表示したテキストについて、
・ .gestureを使って、マウスの移動量を取得、
・ .offsetを使って、Textの表示位置を調整
しました。
@State変数は、ドラッグ終了後も値を保持していますので、ドラッグ後にテキストの位置を知りたい等で参照することもできます。
Sponsor Link