2016-07-27 7 views
1

私はインターネット速度テストアプリを開発しています。私は将来のプロジェクトについてもっと練習して学ぶために何かをするでしょう。setLineDash Swift 2/3に対称的

これは私のスウィフトコード:

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() 
    } 

} 

結果がこれです:私は自動化する必要がある

enter image description here


私がする必要がどのようなこのコード行:

context!.setLineDash(phase: 0, lengths: [2, 54], count: 2) 

長さが数だけ動的にこれを取得するのにかかる最終的な方程式の数を取得するために、計算せずに追加される[2、54]です。 1:ダッシュ12を追加する必要があります(あとで変更でき、変数として割り当てられます)。弧は可変角度で開始し、終了します(後で変更可能)。 2:dashArc.lineWidth = dashWidthの値も変更することができ、12個のダッシュの間のスペースを計算する重要な項目です。 3:提示されたすべての変数は可変であるため、この計算を行う最良の方法です。 最初と最後のダッシュは、それぞれのstartAngleとendAngleと同じ角度にする必要があります。


は私が必要なもの:

は、私が見て、円弧の間にできるだけ左右対称のダッシュを拡散計算を必要としています。

私はこれと同様の計算を考えた:

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

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

context!.setLineDash(phase: 0, lengths: [widthDash, spacing], count: 2) 

しかし、私はperimeterArcを計算する方法がわかりません。 誰かが私を助けることができますか?私はSwift 2/3でこれを論理的に計算するための何かを考えることができませんでした。

私は任意のヒントをありがとうございます。

答えて

2

ダッシュパターンを使用して直接空白を計算しようとするのではなく、まず角度を考えます。

私の本のPostScript By Example(281ページ)に例として作成されたコードをいくつか取り上げました。私はPostscriptコードをSwiftに翻訳しました(バージョン2はバージョン3が役に立たないと思われるので)。

私は、2つの間に奇妙なやりとりがあると感じているので、グラフィックスコンテキストにアクセスして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) 
} 

}

私はこのアプローチははるかに柔軟であると信じ、およびあなたが線の幅を計算するのに必要なトリッキーな計算を避けるダッシュパターンのn '相に対応する。

こちらがお役に立てば幸いです。どう考えているか教えてください。

+0

ありがとうございました!ちょうど私が必要なもの! – James