以Swift 2/3对称设置划线

以Swift 2/3对称设置划线,swift,core-graphics,uibezierpath,Swift,Core Graphics,Uibezierpath,我正在开发一个互联网速度测试应用程序。我将做一些事情来练习和了解更多关于未来项目的信息 这是我的Swift代码: import UIKit @IBDesignable class Arc: UIView { @IBInspectable var dashWidth: CGFloat = 12.0 @IBInspectable var smallDashWidth: CGFloat = 5.0 override func draw(_ rect: CGRect) {

我正在开发一个互联网速度测试应用程序。我将做一些事情来练习和了解更多关于未来项目的信息

这是我的Swift代码:

import UIKit

@IBDesignable
class Arc: UIView {

   @IBInspectable var dashWidth: CGFloat = 12.0
   @IBInspectable var smallDashWidth: CGFloat = 5.0

   override func draw(_ rect: CGRect) {
       // Position and Radius of Arc
       let center = CGPoint(x: bounds.width / 2, y: bounds.height / 2)

       // Calculate Angles
       let π = CGFloat(M_PI)
       let startAngle = 3 * π / 4
       let endAngle = π / 4
       let radius = max(bounds.width / 1.15, bounds.height / 1.15) / 2 - dashWidth / 2

       // Start Context
       let context = UIGraphicsGetCurrentContext()


       // MARK: Base
       let arc = UIBezierPath(arcCenter: center, radius: radius,startAngle: startAngle,endAngle: endAngle,clockwise: true)
       arc.addArc(withCenter: center, radius: radius, startAngle: endAngle, endAngle: startAngle, clockwise: false)
       arc.lineJoinStyle = .bevel
       arc.lineCapStyle = .round
       arc.close()
       UIColor.yellow().setStroke()
       arc.lineWidth = smallDashWidth
       //context!.saveGState()
       context!.setLineDash(phase: 0, lengths: [0, 0], count: 2)
       arc.stroke()
       context!.saveGState()


       // MARK: dash Arc
       let dashArc = UIBezierPath()
       dashArc.addArc(withCenter: center, radius: radius, startAngle: startAngle, endAngle: endAngle, clockwise: true)

       // Round Line
       dashArc.lineJoinStyle = .round;

       // Set Stroke and Width of Dash
       UIColor.white().setStroke()
       dashArc.lineWidth = dashWidth

       // Save Context and Set Line Dash
       context!.saveGState()
       context!.setLineDash(phase: 0, lengths: [2, 54], count: 2)

       // Draw Line
       dashArc.stroke()

       // Restore Context
       context!.restoreGState()
   }

}
结果是:


我需要做什么:

我需要自动化这一行代码:

context!.setLineDash(phase: 0, lengths: [2, 54], count: 2)
长度为[2,54],这些数字是不经计算而相加的,只是为了得到最终的方程数,从而动态地获得该方程。     1:需要在弧上添加破折号12(稍后可能会更改,将其指定为变量)。圆弧以可变角度开始和结束(以后可能更改)。     2:也可以更改
dashArc.lineWidth=dashWidth
的值,这是计算12个破折号之间间距的重要项目。     3:因为所有的变量都可以是变量,所以这是进行此计算的最佳方法。     4:第一个和最后一个破折号的角度应与相应的起始角和结束角相同


我需要什么:

我需要一个计算,看起来和蔓延尽可能对称的虚线在弧

我想到了一个类似的计算:

var numberOfDashes = 12
var perimeterArc = ?
var widthDash = 2

spacing = (perimeterArc - (widthDash * numberOfDashes)) / numberOfDashes

context!.setLineDash(phase: 0, lengths: [widthDash, spacing], count: 2)
但我不知道如何计算周长。 有人能帮我吗?在Swift 2/3中,我想不出任何东西来为这一点创建逻辑计算


我很欣赏任何提示。

与其尝试使用破折号模式直接计算空间,首先,要考虑角度

我在我的书PostScript By example(第281页)中引用了一些最初作为示例创建的代码。我将postscript代码翻译成Swift(版本2,因为版本3似乎没有任何用处)

我还避免了将UIBezierPath与图形上下文的访问混合使用,因为我感觉两者之间存在一些奇怪的交互。UIBezierPath旨在管理封面下的图形上下文

代码如下:

class  ComputeDashes : UIView
{

设insetAmount:CGFloat=40.0

let  numberOfDashes: Int     = 16
let  startAngle:     CGFloat = CGFloat(1.0 * M_PI / 4.0)
let  endAngle:       CGFloat = CGFloat(3.0 * M_PI / 4.0)
let  subtendedAngle: CGFloat = CGFloat(2.0 * M_PI) - CGFloat(2.0 * M_PI / 4.0)

override init(frame: CGRect) {
    super.init(frame: frame)
}

required init(coder: NSCoder) {
    super.init(coder: coder)!
}

override func drawRect(rect: CGRect)
{
    let  insets: UIEdgeInsets = UIEdgeInsetsMake(insetAmount, insetAmount, insetAmount, insetAmount)
    let  newbounds: CGRect = UIEdgeInsetsInsetRect(self.bounds, insets)

    let  centre: CGPoint = CGPointMake(CGRectGetMidX(newbounds), CGRectGetMidY(newbounds))
    let  radius: CGFloat = CGRectGetWidth(newbounds) / 2.0

    let  context: CGContext = UIGraphicsGetCurrentContext()!

    CGContextAddArc(context, centre.x, centre.y, radius, startAngle, endAngle, 1)

    CGContextSetLineWidth(context, 10.0)
    UIColor.magentaColor().set()
    CGContextStrokePath(context)

    //    MARK:  paint dashes

    let  innerRadius: CGFloat = radius * 0.75
    CGContextSaveGState(context)
    CGContextTranslateCTM(context, centre.x, centre.y)

    let  angle = subtendedAngle / CGFloat(numberOfDashes)
    CGContextRotateCTM(context, endAngle)
    for rot in 0...numberOfDashes {
        let  innerPoint: CGPoint = CGPointMake(innerRadius, 0.0)
        CGContextMoveToPoint(context, innerPoint.x, innerPoint.y)
        let  outerPoint: CGPoint = CGPointMake(radius, 0.0)
        CGContextAddLineToPoint(context, outerPoint.x, outerPoint.y)
        CGContextRotateCTM(context, angle)
    }
    CGContextSetLineWidth(context, 2.0)
    UIColor.blackColor().set()
    CGContextStrokePath(context)
    CGContextRestoreGState(context)
}
}

我相信这种方法更加灵活,避免了在破折号模式的“打开”阶段计算线宽所需的复杂计算


我希望这有帮助。让我知道你的想法

非常感谢你!正是我需要的!