实现Quick Path效果时CAShapeLayer与UIBezierPath绘制出现尖角异常如何解决
问题原因及修复方案
核心问题1:addArc参数单位错误
你定义的degrees计算属性作用是将弧度值转换为角度值,但UIBezierPath的addArc方法要求传入的startAngle、endAngle都是弧度值,你当前传入的是角度值,参数完全不符合要求:
// 错误写法:360.degrees等价于将360弧度转换为角度≈20626度,当作弧度传入会导致圆弧绘制完全异常 path.addArc(withCenter: point, radius: width, startAngle: CGFloat(0).degrees, endAngle: CGFloat(360).degrees, clockwise: false)
修改为直接传入弧度值即可:
path.addArc(withCenter: point, radius: width, startAngle: 0, endAngle: .pi * 2, clockwise: false)
核心问题2:偏移方向逻辑错误
你需要的是垂直于两点连线方向的左右偏移点,当前代码里newRight用angle-180的写法,实际是沿着连线的反方向偏移,完全不符合路径边缘的构造逻辑,会直接导致相邻段边缘错位出现尖角:
// 错误写法:左右偏移方向完全错误 let newLeft = point.offset(byDistance: width, inDirection: angle) let newRight = point.offset(byDistance: width, inDirection: angle - 180)
修改为垂直于连线的左右方向即可:
let newLeft = point.offset(byDistance: width, inDirection: angle + 90) let newRight = point.offset(byDistance: width, inDirection: angle - 90)
核心问题3:路径构造逻辑错误
你现在每遍历一个点就生成一个独立的闭合四边形,重复调用close(),相邻段没有平滑衔接,填充时会出现重叠、镂空的异常,同时在路径生成方法里直接调用fill()、stroke()也不符合绘制逻辑,这两个方法应该放在draw(_ rect:)生命周期里执行。
完整修复后代码示例
func path() -> UIBezierPath { let widthMultiplier = maxWidth / CGFloat(points.count) let path = UIBezierPath() guard points.count >= 2 else { return path } var lastPoint = points[0] let initialAngle = lastPoint.angle(to: points[1]) let initialWidth = widthMultiplier * 1 var lastLeft = lastPoint.offset(byDistance: initialWidth/2, inDirection: initialAngle + 90) var lastRight = lastPoint.offset(byDistance: initialWidth/2, inDirection: initialAngle - 90) path.move(to: lastLeft) for (index, point) in points.enumerated() where index > 0 { let angle = lastPoint.angle(to: point) let currentWidth = widthMultiplier * CGFloat(index) let newLeft = point.offset(byDistance: currentWidth/2, inDirection: angle + 90) let newRight = point.offset(byDistance: currentWidth/2, inDirection: angle - 90) path.addLine(to: newLeft) if index == points.count - 1 { path.addArc(withCenter: point, radius: currentWidth/2, startAngle: (angle + 90) * .pi / 180, endAngle: (angle - 90) * .pi / 180, clockwise: true) } path.addLine(to: newRight) path.addLine(to: lastRight) lastLeft = newLeft lastRight = newRight lastPoint = point } path.close() path.lineJoinStyle = .round path.lineCapStyle = .round return path }
内容的提问来源于stack exchange,提问作者Anthony Bell
相关产品推荐
相关产品推荐

