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

绘制时钟UIView时刻度与基圆X轴不对齐问题排查

解决时钟表盘刻度与基础圆错位的问题

嘿,我看到你在绘制时钟表盘时遇到了刻度对齐的问题,咱们来一步步排查并修复这些问题:

核心问题分析

1. 基础圆与刻度的圆心不一致

你在绘制基础圆时,错误地将圆心的x坐标设置为rect.midY,而刻度标记的中心x坐标是rect.midX——这直接导致两个元素的中心不在同一个点上!如果你的ClockView不是正方形,midX和midY数值不同,基础圆的圆心会偏离水平中线,自然和刻度错位。

2. 未定义的变量导致点生成逻辑错误

在circleCircumferencePoints函数中,while循环的判断条件用到了未定义的sides变量,这里应该替换为传入的tickCount参数,否则会导致生成的刻度点数量不符合预期。

3. 圆周点计算的符号问题

当前计算圆周点的公式中,cos和sin前面的负号会导致刻度点的起始方向和旋转逻辑不符合常规时钟布局,调整符号后能让刻度从右侧(0度位置)正确分布。

修正后的完整代码

class ClockView: UIView {
    override func draw(_ rect:CGRect) {
        let ctx = UIGraphicsGetCurrentContext()
        let rad = rect.width / 4
        let endAngle = CGFloat.pi * 2
        
        // 修复:圆心x坐标改为rect.midX,确保和刻度中心一致
        ctx?.addArc(center: CGPoint(x: rect.midX, y: rect.midY), radius: rad, startAngle: 0, endAngle: endAngle, clockwise: true)
        ctx?.setFillColor(UIColor.gray.cgColor)
        ctx?.setStrokeColor(UIColor.white.cgColor)
        ctx?.setLineWidth(4.0)
        ctx?.drawPath(using: .fillStroke)
        
        secondMarkers(ctx!, rect.midX, rect.midY, rad, 48, UIColor.white)
    }
    
    func degree2Radian(a:CGFloat)-> CGFloat {
        let b = CGFloat.pi * a/180
        return b
    }
    
    func secondMarkers(_ ctx: CGContext,_ x: CGFloat,_ y: CGFloat,_ radius: CGFloat,_ tickCount: Int,_ color: UIColor) {
        let points = circleCircumferencePoints(tickCount,x,y,radius)
        var divider: CGFloat = 1/8
        var counter = 0
        
        for p in points {
            if counter % 4 == 0 {
                divider = 1/4
            } else {
                divider = 1/8
            }
            
            let xn = p.x + divider*(x-p.x)
            let yn = p.y + divider*(y-p.y)
            
            let path = CGMutablePath()
            path.move(to: CGPoint(x: p.x, y: p.y))
            path.addLine(to: CGPoint(x: xn, y: yn))
            path.closeSubpath()
            
            ctx.addPath(path)
            counter += 1
        }
        
        let cgcolor = color.cgColor
        ctx.setStrokeColor(cgcolor)
        ctx.setLineWidth(3.0)
        ctx.strokePath()
    }
    
    func circleCircumferencePoints(_ tickCount:Int,_ x:CGFloat,_ y:CGFloat,_ radius:CGFloat,_ adjustment:CGFloat=0)->[CGPoint] {
        let angle = degree2Radian(a: 360/CGFloat(tickCount))
        let cx = x
        let cy = y
        let r = radius
        var i = tickCount
        var points = [CGPoint]()
        
        // 修复:将未定义的sides替换为tickCount
        while points.count < tickCount {
            // 修复:调整cos和sin前面的符号,让刻度从右侧0度位置正确分布
            let xpo = cx + r * cos(angle * CGFloat(i)+degree2Radian(a: adjustment))
            let ypo = cy + r * sin(angle * CGFloat(i)+degree2Radian(a: adjustment))
            points.append(CGPoint(x: xpo, y: ypo))
            i -= 1;
        }
        return points
    }
}

关键修改点标注

  • 基础圆圆心的x坐标从rect.midY改为rect.midX,确保和刻度共享同一中心
  • 将circleCircumferencePoints函数中的sides替换为tickCount,修复循环逻辑
  • 调整圆周点计算时cos和sin的符号,让刻度点的分布符合常规时钟布局

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.28 03:54:08