如何在swiftUI中擦除路径笔划?

问题描述 投票:0回答:1

我试图通过设置 blendMode 修改器来擦除 Path 笔画,但不幸的是,没有像 UIGraphicsBeginImageContext 中那样可用的清晰模式是 setBlendMode(CGBlendMode.clear)

我尝试了所有模式,但没有运气,它会增加颜色,产生一些新的图层颜色。 我认为会有一些机制可以清除底层颜色, 如果您知道请发布答案。 谢谢你。

我的代码:

struct Point : Hashable {
    let x: CGFloat
    let y: CGFloat
    init(_ p:CGPoint) {
       x = p.x
       y = p.y
    }
   func toCGPoint() -> CGPoint {
      CGPoint(x: x, y: y)
   }
}
struct line:Hashable {
    var line:[Point] = []
    var color:Color
    var eraseMode:Bool
}

struct editImage: View {
@State private var eraseMode = false
@State private var lines:[line] = [line(color: .red, eraseMode: false)]
var body: some View {
    ZStack{
        VStack{
            Toggle(isOn: $eraseMode) {
                Text("Erase Mode")
            }.padding(.horizontal)
            .onChange(of: eraseMode) {_eraseMode in
                lines[lines.count-1].eraseMode = _eraseMode
            }
            Button(action: {
                lines.removeAll()
                lines.append(line(color: .green, eraseMode: eraseMode))
            }, label: {
                Text("Clear Canvas").padding()
            })
            ZStack{
                ForEach(lines,id:\.self){line in
                    Path{p in
                        var f = true
                        line.line.forEach { point in
                            if f {
                                p.move(to: point.toCGPoint())
                                f = false
                            }else{
                                p.addLine(to: point.toCGPoint())
                            }
                        }
                        
                    }.stroke(line.color,style: StrokeStyle(lineWidth: 14, lineCap: .round, lineJoin: .bevel, miterLimit: 0, dash: [], dashPhase: 0))
                    .blendMode(line.eraseMode ? BlendMode.hue : BlendMode.normal)
                }
            }.frame(width: 300, height: 300)
            .background(Color.gray)
            .gesture(DragGesture(minimumDistance: 0, coordinateSpace: .local).onChanged({ v in
                lines[lines.count-1].line.append(.init(v.location))
                
            }).onEnded({ _ in
                lines.append(line(color: .red, eraseMode: eraseMode))
            }))
        }
    }
}
}

我需要的是GIF演示;

ios swift swiftui drawing
1个回答
0
投票

可以将blendMode设置为clear,看Apple文档: 静态变量清除:GraphicsContext.BlendMode { get }

使用此模式,您可以像橡皮擦一样使用源图像。 此模式实现等式 R = 0,其中 R 是合成图像。

参见代码示例:

enum Mode {
  case draw
  case eraser
}

struct Line {
  var color: Color
  var points: [CGPoint]
  var mode: Mode
}
struct ContentView: View {
  @State var selectionModeIndex: Int = 0
  @State var lines: [Line] = []
  var body: some View {
    VStack {
      Picker("Mode:", selection: $selectionModeIndex) {
        Text("Draw mode").tag(0)
        Text("Eraser Mode").tag(1)
      }.pickerStyle(.segmented)
      
      Canvas { context, size in
        for line in lines {
          var path = Path()
          path.addLines(line.points)
          if line.mode == .draw {
            context.blendMode = .normal
            context.stroke(path, with: .color(line.color), style: StrokeStyle(lineWidth: 8))
          } else {
            context.blendMode = .clear
            context.stroke(path, with: .color(line.color), style: StrokeStyle(lineWidth: 8))
          }
        }
      }
      .gesture(DragGesture().onChanged({ dragValue in
         print("Changed")
        if lines.isEmpty  {
          lines = [Line(color: .brown, points: [dragValue.startLocation], mode: Mode(rawValue: selectionModeIndex)!)]
        } else {
          var newLine = Line(color: .brown, points: [], mode:  Mode(rawValue: selectionModeIndex)!)
          if dragValue.startLocation != lines[lines.count - 1].points.first {
            // Start a new line
            newLine.points = [dragValue.startLocation]
            lines.append(newLine)
            print("Start new point")
          } else {
            print("Change point event")
            let changedValue = dragValue.location
            // Just append point to last line
            lines[lines.count - 1].points.append(changedValue)
          }
        }
      }))
    }
  }
}
© www.soinside.com 2019 - 2024. All rights reserved.