如何用UIBezierPath绘制交替虚线与点线?现有代码仅显示点
解决UIBezierPath交替虚线和点线的绘制问题
你的代码里有两个关键错误导致只能渲染出点线:
UIBezierPath的lineCapStyle是全局属性,循环里反复赋值只会保留最后一次的设置(你的循环最后i=10是偶数,最终生效的是round线帽),根本没法给路径的不同段落单独设置样式。- 当前的
lineDash数组[0.001, path.lineWidth * 2]配合round线帽,本质就是画连续的圆点——0长度的线段加上圆形线帽,会生成直径等于线宽的圆点,间隔是线宽的2倍。
下面给出两种可行的实现方式:
方式一:逐段切换样式绘制(Core Graphics)
通过Core Graphics逐段绘制,每段切换线帽和虚线模式,精准控制交替效果:
func drawAlternatingDashesAndDots() { let lineWidth: CGFloat = 8 let startX: CGFloat = 10 let endX: CGFloat = 290 let dashLength: CGFloat = lineWidth * 3 // 长划线长度 let segmentGap: CGFloat = lineWidth * 2 // 长划线和圆点的间隔 let dotGap: CGFloat = lineWidth * 2 // 圆点之间的间隔 UIGraphicsBeginImageContextWithOptions(CGSize(width:300, height:20), false, 2) defer { UIGraphicsEndImageContext() } let context = UIGraphicsGetCurrentContext()! UIColor.white.setFill() context.fill(.infinite) UIColor.black.setStroke() context.setLineWidth(lineWidth) var currentX = startX while currentX < endX { // 绘制长划线(方形线帽) context.setLineCap(.square) context.setLineDash(phase: 0, lengths: [dashLength, segmentGap]) context.move(to: CGPoint(x: currentX, y: 10)) let dashEnd = min(currentX + dashLength, endX) context.addLine(to: CGPoint(x: dashEnd, y: 10)) context.strokePath() currentX = dashEnd + segmentGap guard currentX < endX else { break } // 绘制圆点(圆形线帽,用0长度线段实现) context.setLineCap(.round) context.setLineDash(phase: 0, lengths: [0, dotGap]) context.move(to: CGPoint(x: currentX, y: 10)) context.addLine(to: CGPoint(x: currentX, y: 10)) // 0长度线段 context.strokePath() currentX += dotGap } if let image = UIGraphicsGetImageFromCurrentImageContext() { dashDotDashLineView.image = image } }
方式二:双路径叠加(UIBezierPath)
创建两个独立的UIBezierPath,分别绘制长划线和圆点,通过偏移起点实现交替效果,代码更简洁:
func drawAlternatingDashesAndDots() { let lineWidth: CGFloat = 8 let startX: CGFloat = 10 let endX: CGFloat = 290 let dashLength: CGFloat = lineWidth * 3 let gap: CGFloat = lineWidth * 2 let totalCycleLength = dashLength + gap + gap // 长划线+间隔+圆点间隔的总周期 UIGraphicsBeginImageContextWithOptions(CGSize(width:300, height:20), false, 2) defer { UIGraphicsEndImageContext() } UIColor.white.setFill() UIGraphicsGetCurrentContext()!.fill(.infinite) UIColor.black.setStroke() // 绘制长划线路径 let dashPath = UIBezierPath() dashPath.move(to: CGPoint(x: startX, y: 10)) dashPath.addLine(to: CGPoint(x: endX, y: 10)) dashPath.lineWidth = lineWidth dashPath.lineCapStyle = .square dashPath.setLineDash([dashLength, totalCycleLength], count: 2, phase: 0) dashPath.stroke() // 绘制圆点路径 let dotPath = UIBezierPath() dotPath.move(to: CGPoint(x: startX + dashLength + gap, y: 10)) dotPath.addLine(to: CGPoint(x: endX, y: 10)) dotPath.lineWidth = lineWidth dotPath.lineCapStyle = .round dotPath.setLineDash([0, totalCycleLength], count: 2, phase: 0) dotPath.stroke() if let image = UIGraphicsGetImageFromCurrentImageContext() { dashDotDashLineView.image = image } }
内容的提问来源于stack exchange,提问作者narner
相关产品推荐
相关产品推荐

