要求:
- Platform: iOS8.0+
- Language: Swift3.1
- Editor: Xcode8.3.2
本文主要讨论的问题有:
1. 给定等分数N,找到圆上相应的等分位置P1...Pn;
问题1代码实现
fileprivate func one()
{
let N = 10, R: CGFloat = 100
let angle = 360.0/CGFloat(N) * CGFloat.pi/180.0
for i in 0..<N
{
let start = CGFloat(i)*angle - 90*CGFloat.pi/180
let end = start + angle
// 可以利用贝塞尔path获取圆弧终点的位置CGPoint
let path = UIBezierPath(arcCenter: view.center, radius: R, startAngle: start, endAngle: end, clockwise: true)
// 等分点
let position = path.currentPoint
// 在相应等分点上绘制元素
let p = UIBezierPath(arcCenter: position, radius: 10, startAngle: 0, endAngle: 2*CGFloat.pi, clockwise: true)
let layer = CAShapeLayer()
layer.fillColor = UIColor.blue.cgColor
layer.path = p.cgPath
view.layer.addSublayer(layer)
// 等分弧线段
let circleLayer = CAShapeLayer()
circleLayer.lineWidth = 4
circleLayer.fillColor = nil
circleLayer.strokeColor = CGFloat(i).remainder(dividingBy: 2) == 0 ? UIColor.red.cgColor : UIColor.green.cgColor
circleLayer.path = path.cgPath
view.layer.addSublayer(circleLayer)
}
}
实现效果
2. 给定一个弦值W【子元素宽度】和圆的半径R,求最大等分数N;
问题2代码实现 - 但不知这种算法为何不太准确,有待优化
fileprivate func two()
{
let W: CGFloat = 80, R: CGFloat = 100
let angle = 2.0 * atan(W / (2.0*R - W))
let N = Int(2.0 * CGFloat.pi / angle)
for i in 0..<N
{
let start = CGFloat(i)*angle
let end = start + angle
// 可以利用贝塞尔path获取圆弧终点的位置CGPoint
let path = UIBezierPath(arcCenter: view.center, radius: R, startAngle: start, endAngle: end, clockwise: true)
// 等分点
let position = path.currentPoint
// 在相应等分点上绘制元素
let p = UIBezierPath(arcCenter: position, radius: W/2, startAngle: 0, endAngle: 2*CGFloat.pi, clockwise: true)
let layer = CAShapeLayer()
layer.fillColor = UIColor.blue.cgColor
layer.path = p.cgPath
view.layer.addSublayer(layer)
// 等分弧线段
let circleLayer = CAShapeLayer()
circleLayer.lineWidth = 4
circleLayer.fillColor = nil
circleLayer.strokeColor = CGFloat(i).remainder(dividingBy: 2) == 0 ? UIColor.red.cgColor : UIColor.green.cgColor
circleLayer.path = path.cgPath
view.layer.addSublayer(circleLayer)
}
}
实现效果
3. 给定等分数N,求使各个元素不重叠的圆的最大半径R;
问题3代码实现
fileprivate func three()
{
let W: CGFloat = 60, N = 8
let angle = 2*CGFloat.pi / CGFloat(N)
var R = W //默认让半径等于W
// 计算 x 是否 <= w/2
var x = R * sin(angle/2)
while x < W/2+10 { //10为间距
R += 1
x = R * sin(angle/2) //重叠的最小间距
}
for i in 0..<N
{
let start = CGFloat(i)*angle
let end = start + angle
// 可以利用贝塞尔path获取圆弧终点的位置CGPoint
let path = UIBezierPath(arcCenter: view.center, radius: R, startAngle: start, endAngle: end, clockwise: true)
// 等分点
let position = path.currentPoint
// 在相应等分点上绘制元素
let p = UIBezierPath(arcCenter: position, radius: W/2, startAngle: 0, endAngle: 2*CGFloat.pi, clockwise: true)
let layer = CAShapeLayer()
layer.fillColor = UIColor.blue.cgColor
layer.path = p.cgPath
view.layer.addSublayer(layer)
// 等分弧线段
let circleLayer = CAShapeLayer()
circleLayer.lineWidth = 4
circleLayer.fillColor = nil
circleLayer.strokeColor = CGFloat(i).remainder(dividingBy: 2) == 0 ? UIColor.red.cgColor : UIColor.green.cgColor
circleLayer.path = path.cgPath
view.layer.addSublayer(circleLayer)
}
}
实现效果
元素数越多,半径越大
网友评论