2017-05-07 79 views
0

我想沿着圓弧放置UICollectionViewCells(UIBezierPath)。請建議一個公式來計算這些細胞的中心。沿圓弧放置UICollectionViewCells(UIBezierPath)

override func layoutAttributesForItem(at indexPath: IndexPath) -> UICollectionViewLayoutAttributes? { 

} 

所有這些細胞是相同的恆定的尺寸,說(100,100)和兩個小區之間距離x(水平)也是恆定的,說20.

let startAngle: Double = 0 
let endAngle: Double = 180 
var arcRadius: CGFloat = 414 // Actually updated dynamically when layout changes 
var arcCenter: CGPoint { 
    get { 
     return CGPoint(x: contentView.bounds.width/2, y: contentView.bounds.height/2 - arcRadius) 
    } 
} 

func drawArc() { 
    contentView.layer.sublayers?.forEach { 
     if $0 is CAShapeLayer { 
      $0.removeFromSuperlayer() 
     } 
    } 
    // Create an arc 
    let path = UIBezierPath(arcCenter: arcCenter, 
          radius: arcRadius, 
          startAngle: degreesToRadians(value: startAngle), 
          endAngle: degreesToRadians(value: endAngle), 
          clockwise: true) 
    // Create a shape layer and add path 
    let shapeLayer = createShapeLayer() 
    shapeLayer.path = path.cgPath 
    contentView.layer.addSublayer(shapeLayer) 
} 

enter image description here

回答

0

它可以用圓的參數方程來實現。這是我的代碼 -

創建一個Circle對象,然後調用它的func point(startAngle: forItemAtIndex:)找到這些單元格的中心點。

struct Circle { 
    var center: CGPoint 
    var radius: CGFloat 
    func point(startAngle: Double, forItemAtIndex index: Int) -> CGPoint { 
     /* 
     This is based on parametric equation of a circle with center (cx, cy) - 
     x = cx + radius*cos(angle) 
     y = cy + radius*sin(angle) 
     */ 
     var deltaX: CGFloat = 122 // Fixed horizontal (x) distance between 2 cells' centers 
     var deltaY = radius - sqrt(pow(radius, 2) - pow(deltaX, 2)) // formula to calculate vertical distance between cells' centers 
     var actualY = center.y + radius - deltaY 
     var deltaAngleRadians = asin((actualY - center.y)/radius) 
     var deltaAngle = radiansToDegrees(value: deltaAngleRadians) 
     var stepAngle: Double = deltaAngle - startAngle 
     var actualAngle = startAngle + (Double(index)*stepAngle) 
     let viewCenterX = radius * cos(degreesToRadians(value: actualAngle)) + center.x 
     let viewCenterY = radius * sin(degreesToRadians(value: actualAngle)) + center.y 
     var position = CGPoint(x: viewCenterX, y: viewCenterY) 

     return position 
    } 
    func bezierPath(startAngle: Double = 0, endAngle: Double = 180, clockwise: Bool = true) -> UIBezierPath { 
     return UIBezierPath(arcCenter: center, radius: radius, startAngle: degreesToRadians(value: startAngle), endAngle: degreesToRadians(value: endAngle), clockwise: true) 
    } 
    func degreesToRadians(value: Double) -> CGFloat { 
     return CGFloat(value * .pi/180.0) 
    } 
    func radiansToDegrees(value: CGFloat) -> Double { 
     return Double(value * 180.0/.pi) 
    } 
}