如何让时钟标记粘在时钟边框上?

时间:2015-05-08 19:28:59

标签: xcode swift osx-yosemite

我试着快速制作一个时钟,但现在我想做一些奇怪的事情。我想让边框半径可设置。这是容易的部分(很简单,因为我已经这样做了)。我全天抽了60个蜱虫。问题是60个刻度是一个完美的圆圈。如果我改变边界半径,我会得到这个时钟:

enter image description here

所有刻度都是使用NSBezierPath制作的,每个刻度的计算位置代码是:

 let bezierPath = NSBezierPath(roundedRect:self.bounds, xRadius:currentRadius, yRadius:currentRadius) 

point1和point2是12个时钟滴答的点。

我的时钟背景是用bezier路径制作的:

.parallax7 {
   background-color: #FF783E;
   background-image: url('../images/parallax-bg-7.jpg');
   background-size: 100% auto;
}

currentRadius - 是一个可设置的var,所以我的背景是从一个完美的圆(当圆角半径=高度/ 2)到一个正方形(当圆角半径= 0时)。

是否有任何公式计算每个刻度的位置,因此,对于任何边界半径,最后所有刻度与边界的距离是否相同?

1 个答案:

答案 0 :(得分:2)

如果不借助图形图解释数学是相当复杂的,但基本上如果你考虑在时钟中心使用原点的极坐标方法,那么有两种情况:

  • 来自原点的辐条击中正方形的直边 - 通过三角法
  • 它撞击角落处的圆弧 - 我们使用余弦规则来解决由时钟中心,角圆的中心和轮辐穿过角落的点形成的三角形。该三角形的原点 - 角度为45° - angleOfSpoke,其中两个边长度已知。将余弦方程解为二次方并得到它。

这个功能可以做到:

func radiusAtAngle(angleOfSpoke: Double, radius: Double, cornerRadius: Double) -> Double {
    // radius is the half-width of the square, = the full radius of the circle
    // cornerRadius is, of course, the corner radius. 
    // angleOfSpoke is the (maths convention) angle of the spoke
    // the function returns the radius of the spoke.

    let theta = atan((radius - cornerRadius) / radius) // This determines which case

    let modAngle = angleOfSpoke % M_PI_2 // By symmetry we need only consider the first quadrant

    if modAngle <= theta { // it's on the vertical flat
        return radius / cos(modAngle)
    } else if modAngle > M_PI_2 - theta { // it's on the horizontal flat
        return radius / cos(M_PI_2 - modAngle)
    } else { // it's on the corner arc
        // We are using the cosine rule to solve the triangle formed by
        // the clock centre, the curved corner's centre,
        // and the point of intersection of the spoke.
        // Then use quadratic solution to solve for the radius.
        let diagonal = hypot(radius - cornerRadius, radius - cornerRadius)
        let rcosa = diagonal * cos(M_PI_4 - modAngle)
        let sqrTerm = rcosa * rcosa - diagonal * diagonal + cornerRadius * cornerRadius
        if sqrTerm < 0.0 {
            println("Aaargh - Negative term") // Doesn't happen - use assert in production
            return 0.0
        } else {
            return rcosa + sqrt(sqrTerm) // larger of the two solutions
        }
    }
}

图中OP =对角线,OA =半径,PS = PB = cornerRadius,OS =函数返回,BÔX= theta,SÔX= angleOfSpoke

Diagram of solution