【问题标题】:Place UICollectionViewCells along an arc (UIBezierPath)沿弧线放置 UICollectionViewCells (UIBezierPath)
【发布时间】:2017-05-07 21:55:30
【问题描述】:

我想沿圆弧 (UIBezierPath) 放置 UICollectionViewCells。请提出一个计算这些单元格中心的公式。

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

【问题讨论】:

    标签: ios swift uicollectionview trigonometry uibezierpath


    【解决方案1】:

    可以使用圆的参数方程来实现。这是我的代码-

    创建一个Circle 对象,然后调用其函数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)
        }
    }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-08
      • 2014-07-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多