沿着弧放置UICollectionViewCells(UIBezierPath)

时间:2017-05-07 21:55:30

标签: ios swift uicollectionview trigonometry uibezierpath

我想沿着圆弧(UIBezierPath)放置UICollectionViewCells。请建议计算这些细胞中心的公式。

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

所有这些细胞具有相同的恒定大小,例如(100,100),两个细胞之间的x距离(水平)也是恒定的,比如说20。

public class Ctester {

public Ctester(){
    Frame();
}

public void Frame(){

    JFrame fr = new JFrame();
    fr.setVisible(true);
    fr.setSize(500, 500);
    fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
    fr.setResizable(false);

    JPanel p = new JPanel(new GridBagLayout());
    ImageIcon icon = new ImageIcon(getClass().getResource("zippo.jpg"));

    JLabel l = new JLabel(icon)
    JButton bm1 = new JButton("hellu");

    p.add(l);
    p.add(bm1);
    fr.add(p);


}

public static void main(String[]args){
    new Ctester();
}
}

enter image description here

1 个答案:

答案 0 :(得分:1)

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

创建一个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)
    }
}