Swiftui Path Onhover

发布于 2025-02-08 17:55:42 字数 6172 浏览 1 评论 0原文

问题是,。在这种情况下,如检测到的那样,将是一个错误的区域。如何使 .Onhover 路径的修饰符? 例如,带矩形的距离是有效的,但是我现在不这样做。但是矩形现在对我的案例来说是个好主意,因为最可以解决。

struct CenterCategoryPlanView : View {
       @State private var isMouseHover = false
            
       // MARK: Points
       @Binding var startPoint: CGPoint
       @Binding var endPoint: CGPoint
       @Binding var categoryEntity : CategoryEntity
            
       // MARK: Sizes
       @Binding var monthColumnSize : CGSize
            
       var body: some View {
                
           Path { (path) in
               path.move(to: startPoint )
               path.addLine(to: endPoint)
               path.closeSubpath()
           }
           .stroke(style: StrokeStyle(lineWidth: 30, lineCap: .square))
           .onHover(perform: { value in
               print("isHovered: \(value)")
           })
               .foregroundColor(Color(hex: categoryEntity.color ?? ""))
                
           Text(categoryEntity.name ?? "-")
               .position(x: max(monthColumnSize.width, (endPoint.x + startPoint.x) / 2), y: startPoint.y)
               .aspectRatio(1, contentMode: .fill)
               .font(.title2)
            }
}

呼叫所有视图

    struct CategoryRowView: View {
        @Binding var startPoint: CGPoint
        @Binding var endPoint: CGPoint
        
        @Binding var categoryEntity : CategoryEntity
        @Binding var isCategorySelected : Bool
        @Binding var spacing : Double
        @Binding var monthColumnSize : CGSize
        @Binding var sliderSize : CGSize
        
        @State private var isMouseHover = false
        
        @State var fromMonth = 2
        @State var toMonth = 4
        
        @State var itemRowNr : Int = 1
        
        var body: some View {
            
            Text("")
                .onAppear(){
                    CaclulateStartPositions()
                }
            
            ZStack{
                CenterCategoryPlanView(startPoint: $startPoint, endPoint: $endPoint, categoryEntity: $categoryEntity, monthColumnSize: $monthColumnSize, sliderSize: $sliderSize)
                
                if( isMouseHover || true ){
                    // LEFT
                    LeftCategoryPlanView(startPoint: $startPoint, endPoint: $endPoint, sliderSize: $sliderSize, monthColumnSize: $monthColumnSize, isCategorySelected: $isCategorySelected)
                    
                    
                    //RIGHT
                    RightCategoryPlanView(startPoint: $startPoint, endPoint: $endPoint, sliderSize: $sliderSize, monthColumnSize: $monthColumnSize, isCategorySelected: $isCategorySelected)
                }
            }
            
            Color.clear
        }
private func CaclulateStartPositions(){
        startPoint.x = monthColumnSize.width * CGFloat(fromMonth - 1) + sliderSize.width
        startPoint.y = 80
        
        endPoint.x = monthColumnSize.width * CGFloat(toMonth) - sliderSize.width
        endPoint.y = 80
        
        print("startPoint.x: \(startPoint.x)")
        print("startPoint.y: \(startPoint.y)")
    }
        
}

左滑块

struct LeftCategoryPlanView : View {
    
    @Binding var startPoint: CGPoint
    @Binding var endPoint: CGPoint
    
    @Binding var sliderSize : CGSize
    @Binding var monthColumnSize : CGSize
    
    @Binding var isCategorySelected : Bool
    
    var LeftSliderPos : CGPoint {
        get{
            return CGPoint(x: startPoint.x - sliderSize.width / 2, y: startPoint.y)
        }
    }
    
    var body: some View {
        Rectangle()
            .frame(width: sliderSize.width, height: sliderSize.height, alignment: .leading)
            .position(LeftSliderPos)
            .foregroundColor(.gray)
            .gesture(DragGesture()
                .onChanged { (value) in
                    if(value.location.x < endPoint.x)
                    {
                        if(value.location.x < (endPoint.x - monthColumnSize.width / 2)){
                            self.startPoint = CGPoint(x: value.location.x , y: startPoint.y)
                            isCategorySelected = true
                        }
                    }
                }
                .onEnded({ value in
                    isCategorySelected = false
  
                    withAnimation(.easeIn(duration: 0.3)) {
  
                        startPoint.x = startPoint.x - startPoint.x.truncatingRemainder(dividingBy: monthColumnSize.width) + sliderSize.width + 1
                    }
                }))
    }
    
}

右滑块

struct RightCategoryPlanView : View {
    @Binding var startPoint: CGPoint
    @Binding var endPoint: CGPoint
    
    @Binding var sliderSize : CGSize
    @Binding var monthColumnSize : CGSize
    
    @Binding var isCategorySelected : Bool
    
    var RightSliderPos : CGPoint {
        get{
            return CGPoint(x: endPoint.x + sliderSize.width / 2, y: startPoint.y)
        }
    }
    
    var body: some View {
        Rectangle()
            .frame(width: sliderSize.width, height: sliderSize.height)
            .position(RightSliderPos)
            .foregroundColor(.gray)
            .gesture(DragGesture()
                .onChanged { (value) in
                    if(value.location.x > (startPoint.x + monthColumnSize.width / 2)){
                        self.endPoint = CGPoint(x: value.location.x, y: endPoint.y)
                        isCategorySelected = true
                    }
                    
                }
                .onEnded({ value in
                    isCategorySelected = false
                    
                    withAnimation(.easeIn(duration: 0.3)) {
                        endPoint.x = endPoint.x - endPoint.x.truncatingRemainder(dividingBy: monthColumnSize.width) + monthColumnSize.width - sliderSize.width - 1
                    }
                }))
    }
}

The problem is, that .onHover doesn't work on Path. In this case is will be one wrong area as hovered detected. How can I make .onHover modifier for the Path?
For example .onHover with rectangle is works, but I don't now why. But rectangle is now good idea for my case, because is most be resizable.

enter image description here

struct CenterCategoryPlanView : View {
       @State private var isMouseHover = false
            
       // MARK: Points
       @Binding var startPoint: CGPoint
       @Binding var endPoint: CGPoint
       @Binding var categoryEntity : CategoryEntity
            
       // MARK: Sizes
       @Binding var monthColumnSize : CGSize
            
       var body: some View {
                
           Path { (path) in
               path.move(to: startPoint )
               path.addLine(to: endPoint)
               path.closeSubpath()
           }
           .stroke(style: StrokeStyle(lineWidth: 30, lineCap: .square))
           .onHover(perform: { value in
               print("isHovered: \(value)")
           })
               .foregroundColor(Color(hex: categoryEntity.color ?? ""))
                
           Text(categoryEntity.name ?? "-")
               .position(x: max(monthColumnSize.width, (endPoint.x + startPoint.x) / 2), y: startPoint.y)
               .aspectRatio(1, contentMode: .fill)
               .font(.title2)
            }
}

Call all views

    struct CategoryRowView: View {
        @Binding var startPoint: CGPoint
        @Binding var endPoint: CGPoint
        
        @Binding var categoryEntity : CategoryEntity
        @Binding var isCategorySelected : Bool
        @Binding var spacing : Double
        @Binding var monthColumnSize : CGSize
        @Binding var sliderSize : CGSize
        
        @State private var isMouseHover = false
        
        @State var fromMonth = 2
        @State var toMonth = 4
        
        @State var itemRowNr : Int = 1
        
        var body: some View {
            
            Text("")
                .onAppear(){
                    CaclulateStartPositions()
                }
            
            ZStack{
                CenterCategoryPlanView(startPoint: $startPoint, endPoint: $endPoint, categoryEntity: $categoryEntity, monthColumnSize: $monthColumnSize, sliderSize: $sliderSize)
                
                if( isMouseHover || true ){
                    // LEFT
                    LeftCategoryPlanView(startPoint: $startPoint, endPoint: $endPoint, sliderSize: $sliderSize, monthColumnSize: $monthColumnSize, isCategorySelected: $isCategorySelected)
                    
                    
                    //RIGHT
                    RightCategoryPlanView(startPoint: $startPoint, endPoint: $endPoint, sliderSize: $sliderSize, monthColumnSize: $monthColumnSize, isCategorySelected: $isCategorySelected)
                }
            }
            
            Color.clear
        }
private func CaclulateStartPositions(){
        startPoint.x = monthColumnSize.width * CGFloat(fromMonth - 1) + sliderSize.width
        startPoint.y = 80
        
        endPoint.x = monthColumnSize.width * CGFloat(toMonth) - sliderSize.width
        endPoint.y = 80
        
        print("startPoint.x: \(startPoint.x)")
        print("startPoint.y: \(startPoint.y)")
    }
        
}

Left slider

struct LeftCategoryPlanView : View {
    
    @Binding var startPoint: CGPoint
    @Binding var endPoint: CGPoint
    
    @Binding var sliderSize : CGSize
    @Binding var monthColumnSize : CGSize
    
    @Binding var isCategorySelected : Bool
    
    var LeftSliderPos : CGPoint {
        get{
            return CGPoint(x: startPoint.x - sliderSize.width / 2, y: startPoint.y)
        }
    }
    
    var body: some View {
        Rectangle()
            .frame(width: sliderSize.width, height: sliderSize.height, alignment: .leading)
            .position(LeftSliderPos)
            .foregroundColor(.gray)
            .gesture(DragGesture()
                .onChanged { (value) in
                    if(value.location.x < endPoint.x)
                    {
                        if(value.location.x < (endPoint.x - monthColumnSize.width / 2)){
                            self.startPoint = CGPoint(x: value.location.x , y: startPoint.y)
                            isCategorySelected = true
                        }
                    }
                }
                .onEnded({ value in
                    isCategorySelected = false
  
                    withAnimation(.easeIn(duration: 0.3)) {
  
                        startPoint.x = startPoint.x - startPoint.x.truncatingRemainder(dividingBy: monthColumnSize.width) + sliderSize.width + 1
                    }
                }))
    }
    
}

Right slider

struct RightCategoryPlanView : View {
    @Binding var startPoint: CGPoint
    @Binding var endPoint: CGPoint
    
    @Binding var sliderSize : CGSize
    @Binding var monthColumnSize : CGSize
    
    @Binding var isCategorySelected : Bool
    
    var RightSliderPos : CGPoint {
        get{
            return CGPoint(x: endPoint.x + sliderSize.width / 2, y: startPoint.y)
        }
    }
    
    var body: some View {
        Rectangle()
            .frame(width: sliderSize.width, height: sliderSize.height)
            .position(RightSliderPos)
            .foregroundColor(.gray)
            .gesture(DragGesture()
                .onChanged { (value) in
                    if(value.location.x > (startPoint.x + monthColumnSize.width / 2)){
                        self.endPoint = CGPoint(x: value.location.x, y: endPoint.y)
                        isCategorySelected = true
                    }
                    
                }
                .onEnded({ value in
                    isCategorySelected = false
                    
                    withAnimation(.easeIn(duration: 0.3)) {
                        endPoint.x = endPoint.x - endPoint.x.truncatingRemainder(dividingBy: monthColumnSize.width) + monthColumnSize.width - sliderSize.width - 1
                    }
                }))
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。
列表为空,暂无数据
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文