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

UIKit绘图时快速画线UITouch的touchMoved无法连续回调问题

解决UIKit快速画线时UITouch回调不连续的问题

这种情况太常见了——iOS系统为了性能优化,在快速滑动触摸的时候,会自动合并一些相邻的触摸点,导致touchesMoved不会每一个像素都触发回调,这就是你觉得线条断断续续的根源。下面给你两个实用的解决方案:

方案一:插值补全缺失的触摸点

核心思路是:每次收到touchesMoved回调时,计算当前触摸点和上一个点之间的所有中间插值点,逐个绘制图案,填补系统跳过的点,保证线条连续。

补全后的触摸事件处理代码如下:

var tempImageView: UIImageView!
var patternImage = UIImage(named: "xxx.png")!
var brushWidth: CGFloat = 50.0
var opacity: CGFloat = 1.0
var lastPoint = CGPoint.zero

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesBegan(touches, with: event)
    guard let touch = touches.first else { return }
    lastPoint = touch.location(in: tempImageView)
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesMoved(touches, with: event)
    guard let touch = touches.first else { return }
    let currentPoint = touch.location(in: tempImageView)
    
    // 计算插值点,补全中间缺失的路径
    drawInterpolatedPoints(from: lastPoint, to: currentPoint)
    
    lastPoint = currentPoint
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesEnded(touches, with: event)
    // 收尾绘制,避免线条末端不完整
    guard let touch = touches.first else { return }
    let currentPoint = touch.location(in: tempImageView)
    drawInterpolatedPoints(from: lastPoint, to: currentPoint)
}

// 插值绘制的核心方法
private func drawInterpolatedPoints(from start: CGPoint, to end: CGPoint) {
    let distance = hypot(end.x - start.x, end.y - start.y)
    let steps = Int(distance / 2) // 每2个像素画一个点,可根据需求调整密度
    
    UIGraphicsBeginImageContextWithOptions(tempImageView.bounds.size, false, UIScreen.main.scale)
    tempImageView.image?.draw(in: tempImageView.bounds)
    
    for step in 0...steps {
        let t = CGFloat(step) / CGFloat(steps)
        let interpolatedX = start.x + t * (end.x - start.x)
        let interpolatedY = start.y + t * (end.y - start.y)
        let point = CGPoint(x: interpolatedX, y: interpolatedY)
        
        // 把图案绘制到当前插值点(居中对齐)
        patternImage.draw(at: CGPoint(x: point.x - brushWidth/2, y: point.y - brushWidth/2), 
                         blendMode: .normal, 
                         alpha: opacity)
    }
    
    tempImageView.image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
}

方案二:用图案描边路径(更高效)

如果你的需求是绘制连续的图案线条,直接用UIBezierPath创建路径,再将图案设置为路径的描边样式会更合适——系统会自动处理路径连续性,即使touchesMoved回调不频繁,线条依然完整,而且绘制效率更高。

示例代码:

var tempImageView: UIImageView!
var patternImage = UIImage(named: "xxx.png")!
var brushWidth: CGFloat = 50.0
var opacity: CGFloat = 1.0
var currentPath = UIBezierPath()

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesBegan(touches, with: event)
    guard let touch = touches.first else { return }
    let point = touch.location(in: tempImageView)
    currentPath.move(to: point)
}

override func touchesMoved(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesMoved(touches, with: event)
    guard let touch = touches.first else { return }
    let point = touch.location(in: tempImageView)
    currentPath.addLine(to: point)
    updateDrawing()
}

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesEnded(touches, with: event)
    updateDrawing()
    // 重置路径,准备下一次绘制
    currentPath = UIBezierPath()
}

private func updateDrawing() {
    UIGraphicsBeginImageContextWithOptions(tempImageView.bounds.size, false, UIScreen.main.scale)
    tempImageView.image?.draw(in: tempImageView.bounds)
    
    // 创建基于图案的描边颜色
    let patternColor = UIColor(patternImage: patternImage)
    patternColor.setStroke()
    
    currentPath.lineWidth = brushWidth
    currentPath.lineCapStyle = .round // 圆角端点让线条更顺滑
    currentPath.stroke(with: .normal, alpha: opacity)
    
    tempImageView.image = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
}

额外提醒:如果你的图案带透明通道,一定要确保UIGraphicsBeginImageContextWithOptions的第二个参数传false,这样才能保留透明效果。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.20 11:10:56