Swift 時間期間スライダー
TimePeriodSlider
TimePeriodSliderを部品か出来るように切り出せるとベスト。
import Foundation import SwiftUI struct ClockEditView: View { var index: Int @EnvironmentObject var clocksData: ClocksData @Environment(\.presentationMode) var presentationMode @State var startProgress: CGFloat = 0.0 @State var startBarWith: CGFloat = 0.7 @State var endProgress: CGFloat = 0.7 @State var showeEndBar: Bool = false var body: some View { VStack { : : HStack { TimePeriodSlider() } : : } .onAppear() { : } @ViewBuilder func TimePeriodSlider() -> some View { GeometryReader { geometry in let progressBarWith = geometry.size.width - 32.0 ZStack(alignment: .leading) { Rectangle() .strokeBorder(.yellow.opacity(1.00), style: StrokeStyle(lineWidth: 40, lineCap: .round, lineJoin: .round)) Rectangle() .offset(x: progressBarWith * self.startProgress) .strokeBorder(.blue, style: StrokeStyle(lineWidth: 40, lineCap: .round, lineJoin: .round)) .frame(width: progressBarWith * self.startBarWith - (progressBarWith * self.startProgress) + 32.0) if self.showeEndBar == true { Rectangle() .offset(x: geometry.size.width * 0.0) .strokeBorder(.blue, style: StrokeStyle(lineWidth: 40, lineCap: .round, lineJoin: .round)) .frame(width: progressBarWith * self.endProgress + 32.0) } Image(systemName: "s.circle") .font(.callout) .foregroundColor(.blue) .frame(width: 32, height: 32) .background(.white, in: Circle()) .offset(x: progressBarWith * self.startProgress) .gesture( DragGesture() .onChanged({ value in self.onDrag(value: value, with: progressBarWith) }) ) Image(systemName: "e.circle") .font(.callout) .foregroundColor(.blue) .frame(width: 32, height: 32) .background(.white, in: Circle()) .offset(x: (geometry.size.width - 32.0) * self.endProgress) .gesture( DragGesture() .onChanged({ value in self.onDrag(value: value, with: progressBarWith, isStart: false) }) ) } } .frame(width: self.screenBounds().width / 1.1, height: 40) } func onDrag(value: DragGesture.Value, with: CGFloat, isStart: Bool = true) { print(value) print(self.screenBounds().width) print(with) print(self.screenBounds().width - with) var progress = (value.location.x) / with var dispprogress = (value.location.x) / (with) if progress < 0.0 { progress = 0.0 dispprogress = 0.0 } else if progress > 1.0 { progress = 1.0 dispprogress = (with - 32.0) / (with) } self.setProgress(with: with, progress: progress, dispprogress: dispprogress, isStart: isStart) print("\(progress):\(dispprogress)") } func setProgress(with: CGFloat, progress: CGFloat, dispprogress: CGFloat, isStart: Bool = true) { if isStart == true { self.startProgress = progress if startProgress > endProgress { self.startBarWith = 1.0 self.showeEndBar = true } else { self.startBarWith = self.endProgress self.showeEndBar = false } } else { self.endProgress = progress if endProgress < startProgress { self.startBarWith = 1.0 self.showeEndBar = true } else { self.startBarWith = progress self.showeEndBar = false } } } }