I'm trying to run this code using a UIView
subclass:
bgShapeLayer.path = UIBezierPath(arcCenter: CGPoint(x: self.frame.midX , y: self.frame.midY), radius:
100, startAngle: -90.degreesToRadians, endAngle: 270.degreesToRadians, clockwise: true).cgPath
bgShapeLayer.strokeColor = UIColor.white.cgColor
bgShapeLayer.fillColor = UIColor.clear.cgColor
bgShapeLayer.lineWidth = 15
self.layer.addSublayer(bgShapeLayer)
For some reason, this code works (shows something) when I'm using a 375x667 frame, but doesn't work when I use another frame (for example 120x120 or 74x74). Maybe the shape is out of bounds? But why?
If anyone can identify a problem I'll be really grateful if you'll let me know.
Answered full code:
let timeLeftShapeLayer = CAShapeLayer()
let bgShapeLayer = CAShapeLayer()
var timeLeft: TimeInterval = 3783
var endTime: Date?
var timeLabel = UILabel()
var timer = Timer()
let strokeIt = CABasicAnimation(keyPath: "strokeEnd")
func drawBgShape() {
bgShapeLayer.path = UIBezierPath(arcCenter: CGPoint(x: self.frame.midX , y: self.frame.midY), radius:
min(frame.width/2, frame.height/2), startAngle: -90.degreesToRadians, endAngle: 270.degreesToRadians, clockwise: true).cgPath
bgShapeLayer.strokeColor = UIColor.white.cgColor
bgShapeLayer.fillColor = UIColor.clear.cgColor
bgShapeLayer.lineWidth = 15
self.layer.addSublayer(bgShapeLayer)
}
func drawTimeLeftShape() {
timeLeftShapeLayer.path = UIBezierPath(arcCenter: CGPoint(x: self.frame.midX , y: self.frame.midY), radius:
min(frame.width/2, frame.height/2), startAngle: -90.degreesToRadians, endAngle: 270.degreesToRadians, clockwise: true).cgPath
timeLeftShapeLayer.strokeColor = UIColor.red.cgColor
timeLeftShapeLayer.fillColor = UIColor.clear.cgColor
timeLeftShapeLayer.lineWidth = 15
self.layer.addSublayer(timeLeftShapeLayer)
}
func addTimeLabel() {
timeLabel = UILabel(frame: CGRect(x: self.frame.midX-50 ,y: self.frame.midY-25, width: 100, height: 50))
timeLabel.textAlignment = .center
timeLabel.text = timeLeft.time
self.addSubview(timeLabel)
}
override func draw(_ rect: CGRect) {
super.draw(rect)
self.backgroundColor = UIColor(white: 0.94, alpha: 1.0)
drawBgShape()
drawTimeLeftShape()
addTimeLabel()
// here you define the fromValue, toValue and duration of your animation
strokeIt.fromValue = 0
strokeIt.toValue = 1
strokeIt.duration = 60
// add the animation to your timeLeftShapeLayer
timeLeftShapeLayer.add(strokeIt, forKey: nil)
// define the future end time by adding the timeLeft to now Date()
endTime = Date().addingTimeInterval(timeLeft)
timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(updateTime), userInfo: nil, repeats: true)
}
@objc func updateTime() {
if timeLeft > 0 {
timeLeft = endTime?.timeIntervalSinceNow ?? 0
timeLabel.text = timeLeft.time
} else {
timeLabel.text = "00:00"
timer.invalidate()
}
}
Thanks!
Because the radius 100 needs at least a height of 200
so change it to this
let radius = min(frame.width/2, frame.height/2);
Edit this works with me
let df = qw()
df.frame = CGRect.init(x: 0, y: 0, width: 100, height: 100)
self.view.addSubview(df)
import UIKit
class qw: UIView {
// Only override draw() if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func draw(_ rect: CGRect) {
// Drawing code
self.drawTimeLeftShape()
}
let timeLeftShapeLayer = CAShapeLayer()
let bgShapeLayer = CAShapeLayer()
var timeLeft: TimeInterval = 3783
var endTime: Date?
var timeLabel = UILabel()
var timer = Timer()
let strokeIt = CABasicAnimation(keyPath: "strokeEnd")
func drawBgShape() {
bgShapeLayer.path = UIBezierPath(arcCenter: CGPoint(x: self.frame.midX , y: self.frame.midY), radius:
min(frame.width/2, frame.height/2), startAngle: -90.degreesToRadians, endAngle: 270.degreesToRadians, clockwise: true).cgPath
bgShapeLayer.strokeColor = UIColor.white.cgColor
bgShapeLayer.fillColor = UIColor.clear.cgColor
bgShapeLayer.lineWidth = 15
self.layer.addSublayer(bgShapeLayer)
}
func drawTimeLeftShape() {
timeLeftShapeLayer.path = UIBezierPath(arcCenter: CGPoint(x: self.frame.midX , y: self.frame.midY), radius:
min(frame.width/2, frame.height/2), startAngle: -90.degreesToRadians, endAngle: 270.degreesToRadians, clockwise: true).cgPath
timeLeftShapeLayer.strokeColor = UIColor.red.cgColor
timeLeftShapeLayer.fillColor = UIColor.clear.cgColor
timeLeftShapeLayer.lineWidth = 15
self.layer.addSublayer(timeLeftShapeLayer)
}
}
A Demo is here CircleView