如何从 swift 中的第一象限分割圆
How to segment a circle from first quadrant in swift
基本上我想创建一个计时器应用程序。这就是为什么我需要一个圆圈来显示计时器的进度。如果定时器是 10 秒,圆圈将被分成 10 段,每段将在一秒后出现。好的。
我已经从 成功创建了它,但有点问题。我圈子的部分从第四象限开始,但不是预期的。我想显示第一象限的部分。在这里,我为 8 个段创建了这个函数。
请提供可以动态使用的建议
func createCircle(){
let circlePath = UIBezierPath(arcCenter: CGPoint(x: view.frame.size.width/2,y: view.frame.size.height/2), radius: CGFloat(90), startAngle: CGFloat(0), endAngle:CGFloat(M_PI * 2), clockwise: true)
let segmentAngle: CGFloat = (360 * 0.125) / 360
for i in 0 ..< 8 {
let circleLayer = CAShapeLayer()
circleLayer.path = circlePath.CGPath
// start angle is number of segments * the segment angle
circleLayer.strokeStart = segmentAngle * CGFloat(i) //I think all is for this line of code.
print("\nStroke \(i): ",segmentAngle * CGFloat(i))
// end angle is the start plus one segment, minus a little to make a gap
// you'll have to play with this value to get it to look right at the size you need
let gapSize: CGFloat = 0.008
circleLayer.strokeEnd = circleLayer.strokeStart + segmentAngle - gapSize
circleLayer.lineWidth = 10
circleLayer.strokeColor = UIColor(red:0, green:0.004, blue:0.549, alpha:1).CGColor
circleLayer.fillColor = UIColor.clearColor().CGColor
// add the segment to the segments array and to the view
segments.insert(circleLayer, atIndex: i)
}
for i in 0 ..< 8{
view.layer.addSublayer(segments[i])
}
}
使用旋转变换旋转视图/图层,使形状图层路径的零点位于您想要的位置。
您必须偏移您的起始角度:
circleLayer.strokeStart = segmentAngle * CGFloat(i) - M_PI / 2.0
虽然转换也可以解决问题,但我不建议在这种情况下使用转换。如果您以后出于其他原因(动画等)想要进行转换,那么您可能还必须考虑任何当前的转换,这可能会使事情变得更加复杂。
编辑:
我认为您的其他一些代码也可能已关闭。我没有弄清楚发生了什么,而是继续从头开始重写它(使用 Swift 3 语法):
let count: Int = 8
let gapSize: CGFloat = 0.008
let segmentAngleSize: CGFloat = (2.0 * CGFloat(M_PI) - CGFloat(count) * gapSize) / CGFloat(count)
let center = CGPoint(x: view.frame.size.width / 2.0, y: view.frame.size.height / 2.0)
let radius: CGFloat = 90
let lineWidth: CGFloat = 10
let strokeColor = UIColor(red:0, green:0.004, blue:0.549, alpha:1).cgColor
for i in 0 ..< count {
let start = CGFloat(i) * (segmentAngleSize + gapSize) - CGFloat(M_PI / 2.0)
let end = start + segmentAngleSize
let segmentPath = UIBezierPath(arcCenter: center, radius: radius, startAngle: start, endAngle: end, clockwise: true)
let arcLayer = CAShapeLayer()
arcLayer.path = segmentPath.cgPath
arcLayer.fillColor = UIColor.clear.cgColor
arcLayer.strokeColor = strokeColor
arcLayer.lineWidth = lineWidth
self.view.layer.addSublayer(arcLayer)
}
Swift 4 个版本基于@Jake 的回答。
class SegmentView: UIView {
@IBInspectable var segmentNumber: Int = 1
@IBInspectable var lineWidth: CGFloat = 10.0
@IBInspectable var strokeColor: UIColor = .red
var gapSize: CGFloat = 0.07
override func draw(_ rect: CGRect) {
super.draw(rect)
let segmentAngleSize: CGFloat = (2.0 * CGFloat.pi - CGFloat(segmentNumber) * gapSize) / CGFloat(segmentNumber)
let center = CGPoint(x: frame.size.width / 2.0, y: frame.size.height / 2.0)
for i in 0..<segmentNumber {
let start = CGFloat(i) * (segmentAngleSize + gapSize) - .pi / 2.0
let end = start + segmentAngleSize
let segmentPath = UIBezierPath(arcCenter: center, radius: self.frame.width / 2 - lineWidth / 2, startAngle: start, endAngle: end, clockwise: true)
let arcLayer = CAShapeLayer()
arcLayer.path = segmentPath.cgPath
arcLayer.fillColor = UIColor.clear.cgColor
arcLayer.strokeColor = strokeColor.cgColor
arcLayer.lineWidth = lineWidth
layer.addSublayer(arcLayer)
}
}
}
基本上我想创建一个计时器应用程序。这就是为什么我需要一个圆圈来显示计时器的进度。如果定时器是 10 秒,圆圈将被分成 10 段,每段将在一秒后出现。好的。
我已经从
请提供可以动态使用的建议
func createCircle(){
let circlePath = UIBezierPath(arcCenter: CGPoint(x: view.frame.size.width/2,y: view.frame.size.height/2), radius: CGFloat(90), startAngle: CGFloat(0), endAngle:CGFloat(M_PI * 2), clockwise: true)
let segmentAngle: CGFloat = (360 * 0.125) / 360
for i in 0 ..< 8 {
let circleLayer = CAShapeLayer()
circleLayer.path = circlePath.CGPath
// start angle is number of segments * the segment angle
circleLayer.strokeStart = segmentAngle * CGFloat(i) //I think all is for this line of code.
print("\nStroke \(i): ",segmentAngle * CGFloat(i))
// end angle is the start plus one segment, minus a little to make a gap
// you'll have to play with this value to get it to look right at the size you need
let gapSize: CGFloat = 0.008
circleLayer.strokeEnd = circleLayer.strokeStart + segmentAngle - gapSize
circleLayer.lineWidth = 10
circleLayer.strokeColor = UIColor(red:0, green:0.004, blue:0.549, alpha:1).CGColor
circleLayer.fillColor = UIColor.clearColor().CGColor
// add the segment to the segments array and to the view
segments.insert(circleLayer, atIndex: i)
}
for i in 0 ..< 8{
view.layer.addSublayer(segments[i])
}
}
使用旋转变换旋转视图/图层,使形状图层路径的零点位于您想要的位置。
您必须偏移您的起始角度:
circleLayer.strokeStart = segmentAngle * CGFloat(i) - M_PI / 2.0
虽然转换也可以解决问题,但我不建议在这种情况下使用转换。如果您以后出于其他原因(动画等)想要进行转换,那么您可能还必须考虑任何当前的转换,这可能会使事情变得更加复杂。
编辑:
我认为您的其他一些代码也可能已关闭。我没有弄清楚发生了什么,而是继续从头开始重写它(使用 Swift 3 语法):
let count: Int = 8
let gapSize: CGFloat = 0.008
let segmentAngleSize: CGFloat = (2.0 * CGFloat(M_PI) - CGFloat(count) * gapSize) / CGFloat(count)
let center = CGPoint(x: view.frame.size.width / 2.0, y: view.frame.size.height / 2.0)
let radius: CGFloat = 90
let lineWidth: CGFloat = 10
let strokeColor = UIColor(red:0, green:0.004, blue:0.549, alpha:1).cgColor
for i in 0 ..< count {
let start = CGFloat(i) * (segmentAngleSize + gapSize) - CGFloat(M_PI / 2.0)
let end = start + segmentAngleSize
let segmentPath = UIBezierPath(arcCenter: center, radius: radius, startAngle: start, endAngle: end, clockwise: true)
let arcLayer = CAShapeLayer()
arcLayer.path = segmentPath.cgPath
arcLayer.fillColor = UIColor.clear.cgColor
arcLayer.strokeColor = strokeColor
arcLayer.lineWidth = lineWidth
self.view.layer.addSublayer(arcLayer)
}
Swift 4 个版本基于@Jake 的回答。
class SegmentView: UIView {
@IBInspectable var segmentNumber: Int = 1
@IBInspectable var lineWidth: CGFloat = 10.0
@IBInspectable var strokeColor: UIColor = .red
var gapSize: CGFloat = 0.07
override func draw(_ rect: CGRect) {
super.draw(rect)
let segmentAngleSize: CGFloat = (2.0 * CGFloat.pi - CGFloat(segmentNumber) * gapSize) / CGFloat(segmentNumber)
let center = CGPoint(x: frame.size.width / 2.0, y: frame.size.height / 2.0)
for i in 0..<segmentNumber {
let start = CGFloat(i) * (segmentAngleSize + gapSize) - .pi / 2.0
let end = start + segmentAngleSize
let segmentPath = UIBezierPath(arcCenter: center, radius: self.frame.width / 2 - lineWidth / 2, startAngle: start, endAngle: end, clockwise: true)
let arcLayer = CAShapeLayer()
arcLayer.path = segmentPath.cgPath
arcLayer.fillColor = UIColor.clear.cgColor
arcLayer.strokeColor = strokeColor.cgColor
arcLayer.lineWidth = lineWidth
layer.addSublayer(arcLayer)
}
}
}