You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Swift中如何避免绘制时出现多条重叠线条?

Fixing Your Swift Drawing App Issues

Hey there! Let's work through those three drawing problems you're dealing with—slow-drawn lines being too dark, weak overlap darkening, and inconsistent line breaks between fast/slow draws. Here's how to refactor your code to fix everything:

1. Why Slow-Drawn Lines Are Too Dark (And How to Fix It)

The root issue is that your current code redraws a new line segment to tempImageView every time touchesMoved fires. With opacity = 0.5, slow draws mean dozens of overlapping segments that stack up to make the line darker. Instead, we'll accumulate the entire drawing path first, then render it once per update to avoid repeated layering.

2. Making Overlap Darkening More Pronounced

Using the .multiply blend mode instead of .normal when merging strokes into the main image will make overlapping areas darken more noticeably—this mimics how real ink builds up on paper for a more natural effect.

3. Eliminating Line Breaks for Consistent Draws

Adding lineJoin = .round ensures smooth connections between path segments, and rendering the full accumulated path instead of individual segments eliminates breaks from fast movement.

Refactored Code

First, add these properties to your view controller:

private var currentPath: CGMutablePath?
private var currentStrokeColor: UIColor?
private var currentLineWidth: CGFloat = 0.0
private var currentOpacity: CGFloat = 1.0
private var swiped = false
private var lastPoint = CGPoint.zero
// Keep your existing red/green/blue/opacity/brushWidth properties

Then update your touch handling methods:

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first else { return }
    swiped = false
    let startPoint = touch.location(in: view)
    
    // Initialize a new path for the current stroke
    currentPath = CGMutablePath()
    currentPath?.move(to: startPoint)
    currentStrokeColor = UIColor(red: red, green: green, blue: blue, alpha: opacity)
    currentLineWidth = brushWidth
    currentOpacity = opacity
    
    lastPoint = startPoint
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    guard let touch = touches.first, let path = currentPath else { return }
    swiped = true
    let currentPoint = touch.location(in: view)
    path.addLine(to: currentPoint)
    lastPoint = currentPoint
    
    // Redraw the temp image with the full accumulated path
    updateTempImageView()
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    finishDrawing()
}

override func touchesCancelled(_ touches: Set<UITouch>, with event: UIEvent?) {
    finishDrawing()
}

Add these helper methods:

private func updateTempImageView() {
    UIGraphicsBeginImageContext(view.frame.size)
    guard let context = UIGraphicsGetCurrentContext(), 
          let path = currentPath, 
          let strokeColor = currentStrokeColor else {
        UIGraphicsEndImageContext()
        return
    }
    
    // Draw existing main strokes so you can see them while drawing
    mainImageView.image?.draw(in: view.bounds)
    
    // Configure drawing settings for smooth, consistent lines
    context.addPath(path)
    context.setLineCap(.round)
    context.setLineJoin(.round) // Smooths connections between segments
    context.setBlendMode(.normal)
    context.setLineWidth(currentLineWidth)
    context.setStrokeColor(strokeColor.cgColor)
    
    // Stroke the entire path once (no more stacking!)
    context.strokePath()
    
    tempImageView.image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
}

private func finishDrawing() {
    // Handle single taps (draw a dot)
    if !swiped {
        currentPath?.addLine(to: lastPoint)
        updateTempImageView()
    }
    
    // Merge temp stroke into main image with stronger overlap darkening
    UIGraphicsBeginImageContext(mainImageView.frame.size)
    mainImageView.image?.draw(in: view.bounds, blendMode: .normal, alpha: 1.0)
    tempImageView.image?.draw(in: view.bounds, blendMode: .multiply, alpha: currentOpacity)
    
    mainImageView.image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    
    // Reset for next stroke
    tempImageView.image = nil
    currentPath = nil
}

Key Changes Explained

  • Path Accumulation: We build a single path for each stroke instead of drawing individual segments, so slow draws don't stack up dark layers.
  • Smooth Line Joins: setLineJoin(.round) ensures fast-moving segments connect seamlessly, eliminating breaks.
  • Stronger Overlap: .multiply blend mode makes overlapping areas darken significantly more than .normal.
  • Consistent Rendering: The entire stroke is rendered once per update, so fast and slow draws look identical in consistency and brightness.

Give these changes a test run—you should see all your issues resolved!

内容的提问来源于stack exchange,提问作者PorkyTheChop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:54:36