首页 > 解决方案 > 将先前的视图变量附加到滑块视图?

问题描述

我希望当用户在字段中输入一个值时,滑块然后由该值初始化,每个端都有一个单独的输入: 合作社 你会看到我试了一下,在 NozzleNodeView 结构被注释掉之后,滑块 Content2View 结构部分进一步向下有注释:

        struct NozzleNodeView: View {
    //@State private var mhzValueminus
    //@State private var mhzValueplus
    
    @State var diameter = Double()
    @State var radicalsize = Double()//Input
    @State var radicalcircumference = Double()//Input
    @State var radicalarea = Double()//Input
    @State var radicalvolume = Double()//Input
    @State var circumferencearea = Double()//Input
    @State var quartervolume = Double()//Input
    @State var circumference = Double()
    @State var circlearea = Double()
    @State var volume = Double()
    @State var spheresurface = Double()
    @State var diameterpropagation = Double()
    @State var radicalvectordia = Double()//Input
    @State var circumferencepropagation = Double()
    @State var radicalvectorcir = Double()//Input
    @State var circleareapropagation = Double()
    @State var radicalvectorareacir = Double()//Input
    @State var volumepropagation = Double()
    @State var radicalvectorvol = Double()//Input
    @State var spheresurfacepropagation = Double()
    @State var radicalvectorspheresurface = Double()//Input
    @State var nozzlevectordefinition = Double()
    @State var nvdefinition = Double()//Input
    @State var nozzlevectorscaleplus = Double()
    @State var nvdefinitionsp = Double()//Input
    @State var nozzlevectorscaleminus = Double()
    @State var nvdefinitionsm = Double()//Input
    @State var trimdiameter = Double()
    @State var trimcircumference = Double()
    @State var trimcirclearea = Double()
    @State var trimvolume = Double()
    @State var trimspheresurface = Double()
    @State var trimorbitlocation = Double()
    
    
    let formatter: NumberFormatter = {
            let formatter = NumberFormatter()
        formatter.numberStyle = .scientific
        formatter.positiveFormat = "0.###E+0"
        formatter.exponentSymbol = "e"
            return formatter
        }()
    func diameter(diameterresult: Double) -> Double { pow(sqrt(radicalsize * 3), 2) }
    func circumference(circumferenceresult: Double) -> Double { pow(pow(sqrt(radicalcircumference * 3), 2), 2) }
    func circlearea(circlearearesult: Double) -> Double { pow(pow(sqrt(radicalarea * 3), 2), 3) }
    func volume(volumeresult: Double) -> Double { pow(pow(pow(sqrt(radicalvolume * 3), 2), 3), 2) }
    func spheresurface(spheresurfaceresult: Double) -> Double{ pow(pow(pow(sqrt(quartervolume * 3), 2), 3), 2) - pow(pow(sqrt(quartervolume * 3), 2), 3) }
    func diameterpropagation(diameterpropagationresult: Double) -> Double{ pow(sqrt(radicalvectordia * 3), 2) }
    func circumferencepropagation(circumferencepropagationresult: Double) -> Double{ pow(pow(sqrt(radicalvectorcir * 3), 2), 2) }
    func circleareapropagation(circleareapropagationresult: Double) -> Double{ pow(pow(pow(sqrt(radicalvectorareacir * 3), 2), 2), 2) }
    func volumepropagation(volumepropagationresult: Double) -> Double{ pow(pow(pow(pow(sqrt(radicalvectorvol * 3), 2), 2), 2), 3) }
    func spheresurfacepropagation(spheresurfacepropagationresult: Double) -> Double{ pow(pow(pow(pow(sqrt(radicalvectorspheresurface * 3), 2), 2), 2), 3) * (0.25) }
    func nozzlevectordefinition(nozzlevectordefinitionresult: Double) -> Double{ pow(pow(pow(pow(sqrt(nvdefinition * 3), 2), 2), 2), 3) * (0.25) / 8 }
    func nozzlevectorscaleplus(nozzlevectorscaleplusresult: Double) -> Double{ ((pow(pow(pow(pow(sqrt(nvdefinitionsp * 3), 2), 2), 2), 3)) * (0.25 / 8)) / ((pow(pow(pow(sqrt(nvdefinitionsp * 3), 2), 3), 2)) - (pow(pow(sqrt(nvdefinitionsp * 3), 2), 3))) }
    func nozzlevectorscaleminus(nozzlevectorscaleminusresult: Double) -> Double{ ((pow(pow(pow(pow(sqrt(nvdefinitionsm * 3), 2), 2), 2), 3)) * (0.25 / 8)) / ((pow(pow(pow(sqrt(nvdefinitionsm * 3), 2), 3), 2)) - (pow(pow(sqrt(nvdefinitionsm * 3), 2), 3))) }
    
    
    var body: some View{
        VStack(alignment: .center) {
        HStack(alignment: .top) {
                VStack(alignment: .center) {
                
                    
                    ScrollView(.vertical) {
                        
                    VStack(alignment: .center) {
                        HStack(alignment: .center) {
                        Image("CotharticrenArcLakeNozzle300")
                                .shadow(radius: 3)
                        }
                        HStack(alignment: .center) {
                            Image("NozzleArtemis100")
                        Text("DART Edge Nozzle")
                        .font(.largeTitle)
                        .bold()
                        .colorInvert()
                        
                        }
                    }.padding(.top, 20)
                        Divider()
                        
                   
                        HStack(alignment: .top) {
                        VStack(alignment: .leading) {
                
                                    
                            
                                
                                Text("Vector Diameter:")
                                    .font(.callout)
                                    .bold()
                                    .colorInvert()
                                TextField("#", value: self.$radicalvectordia, formatter: formatter)
                                    .colorInvert()
                                
                                    .textFieldStyle(RoundedBorderTextFieldStyle())
                                    .overlay(
                                            RoundedRectangle(cornerRadius: 6)
                                                .stroke(Color.blue, lineWidth: 2)
                                        )
                                    
                                Text("Vector Propagation Diameter : \(diameterpropagation(diameterpropagationresult: radicalvectordia))")
                                    .font(.callout)
                                    .bold()
                                    .frame(width: 150, height: 60, alignment: .leading)
                                    .colorInvert()
                            }.padding()
                                Divider()
                    
                
                    
                                        
                                VStack(alignment: .leading) {
                                    
                                    Text("Vector Circumference:")
                                        .font(.callout)
                                        .bold()
                                        .colorInvert()
                                    TextField("#", value: self.$radicalvectorcir, formatter: formatter)
                                        .colorInvert()
                                    
                                        .textFieldStyle(RoundedBorderTextFieldStyle())
                                        .overlay(
                                                RoundedRectangle(cornerRadius: 6)
                                                    .stroke(Color.blue, lineWidth: 2)
                                            )
                                        
                                    Text("Vector Propagation Circumference: \(circumferencepropagation(circumferencepropagationresult: radicalvectorcir))")
                                        .font(.callout)
                                        .bold()
                                        .frame(width: 150, height: 60, alignment: .leading)
                                        .colorInvert()
                                }.padding()
                                    Divider()
                    
                    VStack(alignment: .leading) {
                        
                        Text("Vector Circle Area:")
                            .font(.callout)
                            .bold()
                            .colorInvert()
                        TextField("#", value: self.$radicalvectorareacir, formatter: formatter)
                            .colorInvert()
                        
                            .textFieldStyle(RoundedBorderTextFieldStyle())
                            .overlay(
                                    RoundedRectangle(cornerRadius: 6)
                                        .stroke(Color.blue, lineWidth: 2)
                                )
                            
                        Text("Vector Propagation Circle Area: \(circleareapropagation(circleareapropagationresult: radicalvectorareacir))")
                            .font(.callout)
                            .bold()
                            .frame(width: 150, height: 60, alignment: .leading)
                            .colorInvert()
                    }.padding()
                        Divider()
                        }
                            HStack(alignment: .top) {
                            VStack(alignment: .leading) {
                    
                                    Text("Vector Volume:")
                                        .font(.callout)
                                        .bold()
                                        .colorInvert()
                                    TextField("#", value: self.$radicalvectorvol, formatter: formatter)
                                        .colorInvert()
                                    
                                        .textFieldStyle(RoundedBorderTextFieldStyle())
                                        .overlay(
                                                RoundedRectangle(cornerRadius: 6)
                                                    .stroke(Color.blue, lineWidth: 2)
                                            )
                                        
                                    Text("Vector Propagation Volume : \(volumepropagation(volumepropagationresult: radicalvectorvol))")
                                        .font(.callout)
                                        .bold()
                                        .frame(width: 150, height: 60, alignment: .leading)
                                        .colorInvert()
                                }.padding()
                                    Divider()
                                
                                VStack(alignment: .leading) {
                        
                                        Text("Vector Sphere Surface:")
                                            .font(.callout)
                                            .bold()
                                            .colorInvert()
                                        TextField("#", value: self.$radicalvectorspheresurface, formatter: formatter)
                                            .colorInvert()
                                        
                                            .textFieldStyle(RoundedBorderTextFieldStyle())
                                            .overlay(
                                                    RoundedRectangle(cornerRadius: 6)
                                                        .stroke(Color.blue, lineWidth: 2)
                                                )
                                            
                                        Text("Vector Propagation Sphere Surface : \(spheresurfacepropagation(spheresurfacepropagationresult: radicalvectorspheresurface))")
                                            .font(.callout)
                                            .bold()
                                            .frame(width: 150, height: 60, alignment: .leading)
                                            .colorInvert()
                                    }.padding()
                                        Divider()
                                
                                VStack(alignment: .leading) {
                        
                                        Text("Nozzle Vector Definition:")
                                            .font(.callout)
                                            .bold()
                                            .colorInvert()
                                        TextField("#", value: self.$nvdefinition, formatter: formatter)
                                            .colorInvert()
                                        
                                            .textFieldStyle(RoundedBorderTextFieldStyle())
                                            .overlay(
                                                    RoundedRectangle(cornerRadius: 6)
                                                        .stroke(Color.blue, lineWidth: 2)
                                                )
                                            
                                        Text("Nozzle vector : \(nozzlevectordefinition(nozzlevectordefinitionresult: nvdefinition))")
                                            .font(.callout)
                                            .bold()
                                            .frame(width: 150, height: 60, alignment: .leading)
                                            .colorInvert()
                                    }.padding()
                                        Divider()
                            }
                                HStack(alignment: .top) {
                                VStack(alignment: .leading) {
                        
                                        Text("Nozzle Scale Plus:")
                                            .font(.callout)
                                            .bold()
                                            .colorInvert()
                                        TextField("#", value: self.$nvdefinitionsp, formatter: formatter)
                                            .colorInvert()
                                        
                                            .textFieldStyle(RoundedBorderTextFieldStyle())
                                            .overlay(
                                                    RoundedRectangle(cornerRadius: 6)
                                                        .stroke(Color.blue, lineWidth: 2)
                                                )
                                            
                                        Text("Nozzle Scale : \(nozzlevectorscaleplus(nozzlevectorscaleplusresult: nvdefinition))")
                                            .font(.callout)
                                            .bold()
                                            .frame(width: 150, height: 60, alignment: .leading)
                                            .colorInvert()
                                    }.padding()
                                        Divider()
                                    
                                    VStack(alignment: .leading) {
                            
                                            Text("Nozzle Scale Minus:")
                                                .font(.callout)
                                                .bold()
                                                .colorInvert()
                                            TextField("#", value: self.$nvdefinitionsm, formatter: formatter)
                                                .colorInvert()
                                            
                                                .textFieldStyle(RoundedBorderTextFieldStyle())
                                                .overlay(
                                                        RoundedRectangle(cornerRadius: 6)
                                                            .stroke(Color.blue, lineWidth: 2)
                                                    )
                                                
                                            Text("Nozzle Scale : \(nozzlevectorscaleminus(nozzlevectorscaleminusresult: nvdefinitionsm))")
                                                .font(.callout)
                                                .bold()
                                                .frame(width: 150, height: 60, alignment: .leading)
                                                .colorInvert()
                                        }.padding()
                                            Divider()
                                
                                    
                                    
                                   
                                    
                                    
                                    
                                    
                                    
                                    
                                
                        }
                        }
                        }
        }
        
    }.frame(width: 900, height: 800, alignment: .center)
            .background(Color.white)
        
        Spacer()
}
}
    
        
@propertyWrapper
struct SliderValue {
    
    var value: Double
    
    init(wrappedValue: Double) {
        self.value = wrappedValue
    }
    
    var wrappedValue: Double {
        get { value }
        set { value = min(max(0.0, newValue), 1.0) }
    }
}

class SliderHandle: ObservableObject {
    
    //Slider Size
    let sliderWidth: CGFloat
    let sliderHeight: CGFloat
    
    //Slider Range
    let sliderValueStart: Double
    let sliderValueRange: Double
    
    //Slider Handle
    var diameter: CGFloat = 40
    var startLocation: CGPoint
    
    //Current Value
    @Published var currentPercentage: SliderValue
    
    //Slider Button Location
    @Published var onDrag: Bool
    @Published var currentLocation: CGPoint
        
    init(sliderWidth: CGFloat, sliderHeight: CGFloat, sliderValueStart: Double, sliderValueEnd: Double, startPercentage: SliderValue) {
        self.sliderWidth = sliderWidth
        self.sliderHeight = sliderHeight
        
        self.sliderValueStart = sliderValueStart
        self.sliderValueRange = sliderValueEnd - sliderValueStart
        
        let startLocation = CGPoint(x: (CGFloat(startPercentage.wrappedValue)/1.0)*sliderWidth, y: sliderHeight/2)
        
        self.startLocation = startLocation
        self.currentLocation = startLocation
        self.currentPercentage = startPercentage
        
        self.onDrag = false
    }
    
    lazy var sliderDragGesture: _EndedGesture<_ChangedGesture<DragGesture>>  = DragGesture()
        .onChanged { value in
            self.onDrag = true
            
            let dragLocation = value.location
            
            //Restrict possible drag area
            self.restrictSliderBtnLocation(dragLocation)
            
            //Get current value
            self.currentPercentage.wrappedValue = Double(self.currentLocation.x / self.sliderWidth)
            
        }.onEnded { _ in
            self.onDrag = false
        }
    
    private func restrictSliderBtnLocation(_ dragLocation: CGPoint) {
        //On Slider Width
        if dragLocation.x > CGPoint.zero.x && dragLocation.x < sliderWidth {
            calcSliderBtnLocation(dragLocation)
        }
    }
    
    private func calcSliderBtnLocation(_ dragLocation: CGPoint) {
        if dragLocation.y != sliderHeight/2 {
            currentLocation = CGPoint(x: dragLocation.x, y: sliderHeight/2)
        } else {
            currentLocation = dragLocation
        }
    }
    
    //Current Value
    var currentValue: Double {
        return sliderValueStart + currentPercentage.wrappedValue * sliderValueRange
    }
}

class CustomSlider: ObservableObject {
    
    //Slider Size
    final let width: CGFloat = 300
    final let lineWidth: CGFloat = 8
    
    //Slider value range from valueStart to valueEnd
    final let valueStart: Double
    final let valueEnd: Double
    
    //Slider Handle
    @Published var highHandle: SliderHandle
    @Published var lowHandle: SliderHandle
    
    //Handle start percentage (also for starting point)@Binding var mhzValue: Float
    @SliderValue var highHandleStartPercentage = 1.0
    @SliderValue var lowHandleStartPercentage = 0.0

    final var anyCancellableHigh: AnyCancellable?
    final var anyCancellableLow: AnyCancellable?
    
    init(start: Double, end: Double) {
        valueStart = start
        valueEnd = end
        
        highHandle = SliderHandle(sliderWidth: width,
                                  sliderHeight: lineWidth,
                                  sliderValueStart: valueStart,
                                  sliderValueEnd: valueEnd,
                                  startPercentage: _highHandleStartPercentage
                                )
        
        lowHandle = SliderHandle(sliderWidth: width,
                                  sliderHeight: lineWidth,
                                  sliderValueStart: valueStart,
                                  sliderValueEnd: valueEnd,
                                  startPercentage: _lowHandleStartPercentage
                                )
        
        anyCancellableHigh = highHandle.objectWillChange.sink { _ in
            self.objectWillChange.send()
        }
        anyCancellableLow = lowHandle.objectWillChange.sink { _ in
            self.objectWillChange.send()
        }
    }
    
    //Percentages between high and low handle
    var percentagesBetween: String {
        return String(format: "%.2f", highHandle.currentPercentage.wrappedValue - lowHandle.currentPercentage.wrappedValue)
    }
    
    //Value between high and low handle
    var valueBetween: String {
        return String(format: "%.2f", highHandle.currentValue - lowHandle.currentValue)
    }
}
struct Content2View: View {
    //@Binding var mhzValueplus: nvdefintionsm
    //@Binding var mhzValueminus: nvdefintionsp
    @ObservedObject var slider = CustomSlider(start: 0/*self.$mhzValueplus*/, end: 100/*self.$mhzValueminus*/)
    
    var body: some View {
       
        
        VStack(alignment: .leading) {
            Text("Value: " + slider.valueBetween)
                .font(.callout)
                .bold()
                .frame(width: 300, height: 30, alignment: .leading)
                .colorInvert()
                
            Text("Percentages: " + slider.percentagesBetween)
                .font(.callout)
                .bold()
                .frame(width: 300, height: 30, alignment: .leading)
                .colorInvert()
                
            Text("High Value: \(slider.highHandle.currentValue)")
                .font(.callout)
                .bold()
                .frame(width: 300, height: 30, alignment: .leading)
                .colorInvert()
                
            Text("Low Value: \(slider.lowHandle.currentValue)")
                .font(.callout)
                .bold()
                .frame(width: 300, height: 30, alignment: .leading)
                .colorInvert()
                .padding(.bottom, 30)
            
            //Slider
            SliderView(slider: slider)
        
  
        }.padding(.top, 20).padding(.bottom, 50).frame(width: 400, height: 250, alignment: .center).overlay(
            RoundedRectangle(cornerRadius: 6)
                .stroke(Color.blue, lineWidth: 2)
        ).shadow(radius: 3)
        Spacer()
    }
}

struct SliderView: View {
    @ObservedObject var slider: CustomSlider
    
    var body: some View {
        RoundedRectangle(cornerRadius: slider.lineWidth)
            .fill(Color.blue.opacity(0.2))
            .frame(width: slider.width, height: slider.lineWidth)
            .overlay(
                ZStack {
                    //Path between both handles
                    SliderPathBetweenView(slider: slider)
                    
                    //Low Handle
                    SliderHandleView(handle: slider.lowHandle)
                        .highPriorityGesture(slider.lowHandle.sliderDragGesture)
                    
                    //High Handle
                    SliderHandleView(handle: slider.highHandle)
                        .highPriorityGesture(slider.highHandle.sliderDragGesture)
                }
            )
    }
}

struct SliderHandleView: View {
    @ObservedObject var handle: SliderHandle
    
    var body: some View {
        Circle()
            .frame(width: handle.diameter, height: handle.diameter)
            .foregroundColor(.white)
            .shadow(color: Color.black.opacity(0.15), radius: 8, x: 0, y: 0)
            .scaleEffect(handle.onDrag ? 1.3 : 1)
            .contentShape(Rectangle())
            .position(x: handle.currentLocation.x, y: handle.currentLocation.y)
    }
}

struct SliderPathBetweenView: View {
    @ObservedObject var slider: CustomSlider
    
    var body: some View {
        Path { path in
            path.move(to: slider.lowHandle.currentLocation)
            path.addLine(to: slider.highHandle.currentLocation)
        }
        .stroke(Color.green, lineWidth: slider.lineWidth)
        
    }
   
}

标签: swiftmacosvariablesswiftui

解决方案


推荐阅读