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
相关产品推荐
相关产品推荐

