Ok I have a custom UIProgressView in shape of a circle implemented here:
class PlaybackLineView: UIView {
var percentage: Float = 0.0 {
didSet {
if percentage > 1 {
//print("happned!")
percentage = 1.0
}
DispatchQueue.main.async {
self.setNeedsDisplay()
}
}
}
override func draw(_ rect: CGRect) {
let playbackRed = UIColor(red: 181/255.0, green: 23/255.0, blue: 65/255.0, alpha: 1.0)
playbackRed.setFill()
playbackRed.setStroke()
let newWidth = rect.size.width * CGFloat(percentage)
let fillRect = CGRect(x: 0, y: 0, width: newWidth, height: rect.size.height)
let fillRectPath = UIBezierPath(rect: fillRect)
fillRectPath.fill()
}
@IBInspectable public var drawEndPoint: Bool = true
@IBInspectable public var drawWhenZero: Bool = false
@IBInspectable public var strokeWidth: CGFloat = 3.0
let smallCircleRadius: CGFloat = 6.0
var fullCirclePath: UIBezierPath!
override func draw(_ rect: CGRect) {
if !drawWhenZero && (percentage == 0 || percentage == 1) { return }
UIColor.clear.setFill()
let arcCenter = CGPoint(x: rect.midX, y: rect.midY)
let radius = (rect.width - smallCircleRadius * 2) / 2.0
let circleGray = UIColor(red: 218/255.0, green: 218/255.0, blue: 218/255.0, alpha: 1.0)
circleGray.setStroke()
fullCirclePath = UIBezierPath(arcCenter: arcCenter, radius: radius, startAngle: 0.0, endAngle:CGFloat.pi * 2, clockwise: true)
fullCirclePath.lineWidth = strokeWidth
fullCirclePath.fill()
fullCirclePath.stroke()
let circleRed = UIColor(red: 181/255.0, green: 23/255.0, blue: 65/255.0, alpha: 1.0)
circleRed.setStroke()
let arcPath = UIBezierPath(arcCenter: arcCenter, radius: radius, startAngle: 0.0, endAngle:CGFloat.pi * 2 * CGFloat(percentage), clockwise: true)
arcPath.fill()
arcPath.stroke()
arcPath.lineWidth = strokeWidth
if !drawEndPoint { return }
let smallCirclePath = UIBezierPath(arcCenter: arcPath.currentPoint, radius: smallCircleRadius, startAngle: 0.0, endAngle:CGFloat.pi * 2, clockwise: true)
circleRed.setFill()
smallCirclePath.fill()
smallCirclePath.stroke()
self.transform = CGAffineTransform(rotationAngle: (-90).degreesToRadians)
}
This moves the small circle along the path of the larger circle according to percentage
. Issue is I need to allow the user to control this percentage by tapping/scrubbing ON the UIBezierPath -
So far Ive gotten this that gets whether the tap was within the larger circle:
override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
if let touch = touches.first {
let currentPoint = touch.location(in: self)
// do something with your currentPoint
if(fullCirclePath.contains(currentPoint))
{
print("CONTAINS!: ", currentPoint)
//percentage = 0.5
}
}
}
How do I get how much (in percentage) of the larger circle the tap is along the path, from this CGPoint?
What Ive tried:
override func touchesBegan(_ touches: Set, with event: UIEvent?) { if let touch = touches.first { let currentPoint = touch.location(in: self) // do something with your currentPoint
//print(fullCirclePath.cgPath.cen)
if(fullCirclePath.contains(currentPoint))
{
touchAngle = atan2((currentPoint.x-arcCenter.x), (currentPoint.y-arcCenter.y))
percentage = Float(touchAngle * 100)/Float(M_PI * 2)
print("CONTAINS!: ", currentPoint, "Angle: ", touchAngle.radiansToDegrees, " Percent: ", percentage)
if(AudioPlayerManager.shared.isPlaying())
{
AudioPlayerManager.shared.seek(toProgress: percentage)
}
}
}
}