代码之家  ›  专栏  ›  技术社区  ›  Chris

绘制的圆未对齐

  •  0
  • Chris  · 技术社区  · 8 年前

    我正在尝试绘制一个钟面uiview,并参考了 this example .

    我已经成功地画出了包括股票标记在内的基圆,但是,似乎重叠的圆在x轴上没有对齐,股票标记圆从基圆的右侧伸出。我感到困惑的是,这些圆共享相同的x/y中心坐标,我承认丢失了。。

    以下是参考代码。。。

    class ClockView: UIView {
    
    override func draw(_ rect:CGRect)
    
    {
        let ctx = UIGraphicsGetCurrentContext()
    
        let rad = rect.width / 4
    
        let endAngle = CGFloat.pi * 2
    
        ctx?.addArc(center: CGPoint(x: rect.midY, 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]()
        while points.count <= sides {
            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
    }
    }
    
    1 回复  |  直到 8 年前
        1
  •  2
  •   vacawama    8 年前

    我在一个操场上尝试了您的代码,其中包含以下视图:

    let clock = ClockView(frame: CGRect(x: 0, y: 0, width: 500, height: 400))
    

    结果是:

    clock in Playground

    您的问题是这一行:

    ctx?.addArc(center: CGPoint(x: rect.midY, y: rect.midY), radius: rad, startAngle: 0, endAngle: endAngle, clockwise: true)
    

    您正在使用 rect.midY 作为视图的水平中心,我假设您的视图不是方形的。将其更改为 rect.midX :

    ctx?.addArc(center: CGPoint(x: rect.midX, y: rect.midY), radius: rad, startAngle: 0, endAngle: endAngle, clockwise: true)
    

    其他问题:

    1. sides 未定义。我只是把它设置为 60 来编译它。
    2. 您使用的值为 48 在你的时间里 60 一小时后。

      更改:

      secondMarkers(ctx!, rect.midX, rect.midY, rad, 48, UIColor.white)
      

      致:

      secondMarkers(ctx!, rect.midX, rect.midY, rad, 60, UIColor.white)
      
    3. 您需要一个更长的分隔符 5 滴答声,不是 4 .

      更改:

      if counter % 4 == 0 {
      

      致:

      if counter % 5 == 0 {
      

    根据建议的更改,现在的结果是:

    clock after


    以下是完整的代码:

    class ClockView: UIView {
    
        let sides = 60
    
        override func draw(_ rect:CGRect)
    
        {
            let ctx = UIGraphicsGetCurrentContext()
    
            let rad = rect.width / 4
    
            let endAngle = CGFloat.pi * 2
    
            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, 60, 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 % 5 == 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]()
            while points.count <= sides {
                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
        }
    }
    
    let clock = ClockView(frame: CGRect(x: 0, y: 0, width: 500, height: 400))