UIViewのoverride func touchesMoved() のtouchesは色々な情報を含んでいますが、その中のtouches: Set<UITouch>を利用しています。
ポイントとしては。。。
scaleBar.layer.anchorPointのイニシャル値はセンター(0.5, 0.5)ですが、(0.5, 1)とすることでshapeの底辺中央をanchorPointに設定できます。
iOSではy値はその自身の左上コーナーを基点とするので、自身のheightからy値を引いたものをyValueとし、scaleBy(x: 1, yValue)でy方向にのみscaleさせています。
0 <= yValue <= height としたいため、max(min(height, touch.location(in: self).y), 0) としています。
RxSwiftのBehaviorRelayを使って、スライダーの値が変化する度にUIなどを変更出来るようにしています。
lazy var scaleBar: UIView = {
let scaleBar = UIView()
scaleBar.translatesAutoresizingMaskIntoConstraints = false
scaleBar.backgroundColor = .blue
// initial anchorPoint is (0.5, 0.5) and the shape stretches from the center
scaleBar.layer.anchorPoint = CGPoint(x: 0.5, y: 1)
return scaleBar
}()
override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
guard let touch = touches.first else { return }
let yValue = height - max(min(height, touch.location(in: self).y), 0)
yValueRelay.accept(yValue)
scaleBar.transform = startTransform?.scaledBy(x: 1, y: yValue) ?? CGAffineTransform.identity
}