Closed tsonobe1 closed 1 year ago
例えば、Timelineの拡大率が5のときは、画面上で60分移動すると、DragGestureのvalue.translation.heightは150移動する。 value.translation.heightは、移動する前の場所から移動後までの移動量
各拡大率時の比を表にすると以下の通り
画面上のX分 | 座標の移動量(CGFloat) |
---|---|
60 | 30.0 |
1 | 0.5 |
画面上のX分 | 座標の移動量(CGFloat) |
---|---|
60 | 60.0 |
1 | 1 |
画面上のX分 | 座標の移動量(CGFloat) |
---|---|
60 | 150.0 |
1 | 2.5 |
画面上のX分 | 座標の移動量(CGFloat) |
---|---|
60 | 300.0 |
1 | 5 |
画面上のX分 | 座標の移動量(CGFloat) |
---|---|
60 | 900.0 |
1 | 15 |
value.translation.heightをTaskBoxの上辺・下辺と、時間表示にそのまま代入すると、上表のような比の差異があるので、調整する必要がある。 また、CGFloatは小数点も含むので、5分刻み、15分きざみなどで移動させることができない。 拡大率によっては使いづらいので、好みの倍数で切り捨てたほうがよい
例えば、拡大率が5で、画面上で5分ずつキリよく移動させたい場合は、上表に当てはめて考えてみる。
Timelineの拡大率 5 | 画面上のX分 | 座標の移動量(CGFloat) |
---|---|---|
60 | 150.0 | |
1 | 2.5 | |
5 | 12.5 |
5分の移動のときは、座標を12.5移動させると良いということがわかる なので、value.translation.heightを12.5ごとに切り捨てればよい。 ExcelのFloor()関数だと、丸められる値(number)と、丸めたい倍数(Multiple)を指定すれば、numberをMultipleごとに区切ることができる。
swiftのfloor()関数ではMultipleがないので、独自に実装すればよい。
let x = value.translation.height / 12.5
let y = floor(x) // 切り捨てる
let z = y * 12.5
これで、12.4なら0になり、12.6なら12.5になり、24.9なら25.0になり、27なら25.0になり...と、12.5ずつ区切られる。 こんな感じで、Timelineの拡大率と、各拡大率の画面上のX分と座標の移動量の比と、区切りたい分数を整理して、それぞれの拡大率に応じて使い回せるようにしたのが以下の関数
func floorWithMultiple(_ movePosition: CGFloat, _ positionsMultiple: CGFloat, _ datesMultiple: Double) -> (movedPosition: CGFloat, movedMinute: Int) {
let x = movePosition / positionsMultiple //
let y = floor(x)
let a = y * positionsMultiple
let b = Int(y * datesMultiple)
return (a, b)
}
使う時はこう
DragGesture()
.onChanged { value in
// ドラッグ中の処理
var floored = floorWithMultiple(value.translation.height, 7.5, 15)
switch magnifyBy
case 1.0: floored = floorWithMultiple(value.translation.height, 7.5, 15) // 拡大率 = 1, 15分区切りで移動
case 2.0: floored = floorWithMultiple(value.translation.height, 15, 15) // 拡大率 = 2, 15分区切りで移動
case 5.0: floored = floorWithMultiple(value.translation.height, 12.5, 5) // 拡大率 = 5, 5分区切りで移動
case 10.0: floored = floorWithMultiple(value.translation.height, 5, 1) // 拡大率 = 10, 1分区切りで移動
case 30.0: floored = floorWithMultiple(value.translation.height, 15, 1) // 拡大率 = 30, 1分区切りで移動
default:
print("What?")
}
changedPosition = floored.movedPosition
changedDate = floored.movedMinute
}
以下のように、DragでTaskの開始時刻や、終了時刻、時刻自体を変更する時、座標(CGFloat)とTimlineの時刻の比を整理して、座標の値と見た目場の値を合わせないといけない。