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

iOS中UIBezierPath结合DragGesture快速画圆出现棱角问题求助

iOS绘图问题:快速画圆出现棱角,线条不平滑

在iOS应用里用UIBezierPath配合拖拽手势绘图,收集触摸点添加到路径后描边,但快速画圆时,路径的连接点会形成明显棱角,看起来像多边形,严重影响绘图质感。

用到的核心代码如下:

func draw(size: CGSize, drawingImage: UIImage, lines: [Line], path: UIBezierPath) -> UIImage? {
    UIGraphicsBeginImageContextWithOptions(size, false, 1.0)
    drawingImage.draw(at: .zero)
    
    let pathCount = lines.count
    let pointCount = lines[pathCount-1].line.count
    let point = lines[pathCount-1].line[pointCount-1]
    
    path.addLine(to: point.toCGPoint())
    
    let context = UIGraphicsGetCurrentContext()!
    context.addPath(path.cgPath)
    context.setStrokeColor(Color.white.cgColor)
    
    path.lineWidth = 50
    path.lineCapStyle = .round
    path.lineJoinStyle = .round
    
    path.stroke()

    let myImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return myImage
}

解决思路与方案

问题根源

快速拖拽时,系统捕捉的触摸点间距会变大,直接用addLine(to:)把这些点连起来,就是一段段直线,哪怕设置了lineJoinStyle = .round,也只能让转角处稍微圆润,但直线段本身的棱角消不掉,所以画出来的圆会变成多边形。

具体解决方法:用贝塞尔曲线替代直线连接

把相邻触摸点之间的直线,换成二次贝塞尔曲线,通过计算点的中点作为控制点,让路径自然平滑过渡,彻底消除棱角。

修改后的绘图代码

重构绘图逻辑,不再直接累加直线,而是对每一段线条生成平滑曲线:

func draw(size: CGSize, drawingImage: UIImage, lines: [Line]) -> UIImage? {
    UIGraphicsBeginImageContextWithOptions(size, false, 1.0)
    drawingImage.draw(at: .zero)
    
    let context = UIGraphicsGetCurrentContext()!
    // 统一设置绘图样式,避免重复操作
    context.setStrokeColor(Color.white.cgColor)
    context.setLineWidth(50)
    context.setLineCap(.round)
    context.setLineJoin(.round)
    
    // 遍历所有已绘制线条
    for line in lines {
        let points = line.line.map { $0.toCGPoint() }
        guard points.count > 1 else { continue }
        
        let path = UIBezierPath()
        path.move(to: points[0])
        
        // 用二次贝塞尔曲线连接所有点
        for i in 1..<points.count {
            let prevPoint = points[i-1]
            let currPoint = points[i]
            let midPoint = CGPoint(x: (prevPoint.x + currPoint.x)/2, y: (prevPoint.y + currPoint.y)/2)
            
            if i == 1 {
                // 第一段曲线:从起点到中点,起点作为控制点
                path.addQuadCurve(to: midPoint, controlPoint: prevPoint)
            } else {
                // 中间段曲线:以上一段的中点为起点,当前中点为终点,上一个点为控制点
                let lastMid = CGPoint(x: (points[i-2].x + prevPoint.x)/2, y: (points[i-2].y + prevPoint.y)/2)
                path.replaceLastPoint(with: lastMid)
                path.addQuadCurve(to: midPoint, controlPoint: prevPoint)
            }
            
            // 最后一段:连接到最终的触摸点
            if i == points.count - 1 {
                path.addQuadCurve(to: currPoint, controlPoint: midPoint)
            }
        }
        
        path.stroke()
    }
    
    let finalImage = UIGraphicsGetImageFromCurrentImageContext()
    UIGraphicsEndImageContext()
    return finalImage
}

额外优化技巧

  • 精简触摸点:对收集到的触摸点做去重或简化处理(比如过滤距离过近的点),减少计算量同时不影响平滑度
  • 提升触摸采样率:调整拖拽手势的识别参数,让系统捕捉更密集的触摸点,基础点越密,曲线平滑度越高
  • 改用CAShapeLayer实时渲染:如果是实时绘图场景,用CAShapeLayer承载路径,系统会自动优化渲染效果,比每次生成UIImage更高效流畅

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.20 09:02:44