ZStackにおけるViewについて考察する(002,タップ座標を十字カーソルで表示)
この記事は下記の記事の続きです。
タップした座標を十字線を使って確認しやすくしてみます。
ZStack でタップを検出する Rectangle の上に、Path というビューを置いて、そこに十字線を描画します。
ZStackにおけるビューの配置は下記のようになっています。
最背面から
(0) タップの内側、外側を知らせるために色が変わる Rectangle
(1) タップされた座標を知るための onTapGesture モディファイアが定義された Rectangle
(2) タップされた座標の十字線を描画するための Path
(3) 内部変数を確認するための Text
という順に重ねています。
88行目に示すように、Path の描画領域の大きさは .frame モディファイアを使って上記の (1) の Rectangle と同じ大きさに設定します。Path の位置は、Rectangle や Text と同様に ZStack で管理されているので画面の真ん中に配置されます。
import SwiftUI
struct ContentView: View {
let RECT_W: CGFloat = 320
let RECT_H: CGFloat = 640
let COLOR_RECT: Color = Color.blue
let COLOR_TEXT: Color = Color.white
let COLOR_INSIDE: Color = Color( red: 0x00, green: 0xff, blue: 0x00, opacity: 0xff )
let COLOR_OUTSIDE: Color = Color( red: 0xff, green: 0x00, blue: 0x00, opacity: 0xff )
let CURSOR_COLOR: Color = Color.yellow
let CURSOR_LINE_WIDTH: CGFloat = 3.0
@State var TapX: CGFloat = 0.0
@State var TapY: CGFloat = 0.0
@State var InsideRectTapX: CGFloat = 0.0
@State var InsideRectTapY: CGFloat = 0.0
@State var FlagInsideRect = true
var body: some View {
ZStack{
// 最背面.
Rectangle()
.foregroundColor( FlagInsideRect ? COLOR_INSIDE : COLOR_OUTSIDE )
// 中層面.
Rectangle()
.frame( width: RECT_W, height: RECT_H ) // サイズを指定する.
.foregroundColor( COLOR_RECT ) // 色を指定する.
.onTapGesture {
tap in
TapX = tap.x
TapY = tap.y
// いったんそのままタップ座標を代入する.
InsideRectTapX = TapX
InsideRectTapY = TapY
// いったんフラグを真にしておく.
FlagInsideRect = true
// Rectangleの内側か外側か判定して InsideRectTapXとY を調整する.
if ( InsideRectTapX < 0.0 ){
InsideRectTapX = 0.0;
FlagInsideRect = false
}
if ( InsideRectTapY < 0.0 ){
InsideRectTapY = 0.0
FlagInsideRect = false
}
if ( InsideRectTapX >= RECT_W ){
InsideRectTapX = RECT_W - 1
FlagInsideRect = false
}
if ( InsideRectTapY >= RECT_H ){
InsideRectTapY = RECT_H - 1
FlagInsideRect = false
}
}
// 十字カーソルを描画する.
Path { path in
let the_x = InsideRectTapX
let the_y = InsideRectTapY
// 始点から終点にむかって線分を引く(垂直線).
path.move(to: CGPoint(x: the_x, y: 0 ))
path.addLine(to: CGPoint(x: the_x, y: RECT_H ))
// 始点から終点にむかって線分を引く(水平線).
path.move(to: CGPoint(x: 0, y: the_y ))
path.addLine(to: CGPoint(x: RECT_W, y: the_y ))
}
.stroke( CURSOR_COLOR, lineWidth: CURSOR_LINE_WIDTH )
.frame( width: RECT_W, height: RECT_H )
// 最前面.
VStack{
Text( String( format: "Rectangle WH %.1f * %.1f", RECT_W, RECT_H ))
.foregroundColor( COLOR_TEXT )
Text( String( format: "TapXY( %.1f, %.1f )", TapX, TapY ))
.foregroundColor( COLOR_TEXT )
Text( String( format: "InsideRectTapXY( %.1f, %.1f )", InsideRectTapX, InsideRectTapY ))
.foregroundColor( COLOR_TEXT )
Text( String( format: "FlagInsideRect is %d", FlagInsideRect ))
.foregroundColor( COLOR_TEXT )
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}