title: Giving a CAShapeLayer a 3d effect
body: <p>I am playing around with countdown timer in swift. What I want to  give the countdown circle a 3D shadow of effect.
  the code below will operate the countdown time perfectly but i guess its more of the visuals i am trying to edit with it. is there any way to make the countdown circle larger and while giving it a 3d effect. If you run the code you will see it is just a 2d type of fill. I have been playing around with overlapping circles with a different color and alpha like a dark color to try and make it look more 3d, but Its definitely not the most efficient because it involves drawing multiple circles at once. Is there a way to get a similar 3d effect like the image below without having to redraw multiple overlapping circles. the code below is for the basic 2d flat version of the counter.</p>
  <pre><code>//for countdown timer: ----------------
  let timeLeftShapeLayer = CAShapeLayer()
  let bgShapeLayer = CAShapeLayer()
  var timeLeft: TimeInterval = 10
  var endTime: Date?
  var timeLabel =  UILabel()
  var timer = Timer()
  // here you create your basic animation object to animate the strokeEnd
  let strokeIt = CABasicAnimation(keyPath: &quot;strokeEnd&quot;)
  
  func drawBgShape() {
      bgShapeLayer.path = UIBezierPath(arcCenter: CGPoint(x: view.frame.midX , y: view.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
      view.layer.addSublayer(bgShapeLayer)
  }
  func drawTimeLeftShape() {
      timeLeftShapeLayer.path = UIBezierPath(arcCenter: CGPoint(x: view.frame.midX , y: view.frame.midY), radius:
          100, startAngle: -90.degreesToRadians, endAngle: 270.degreesToRadians, clockwise: true).cgPath
      timeLeftShapeLayer.strokeColor = UIColor.red.cgColor
      timeLeftShapeLayer.fillColor = UIColor.clear.cgColor
      timeLeftShapeLayer.lineWidth = 15
      view.layer.addSublayer(timeLeftShapeLayer)
  }
  
  func addTimeLabel() {
      timeLabel = UILabel(frame: CGRect(x: view.frame.midX-50 ,y: view.frame.midY/3, width: 100, height: 50))
      timeLabel.textAlignment = .center
      timeLabel.text = timeLeft.time
      view.addSubview(timeLabel)
  }
  
  @objc func updateTime() {
      if timeLeft &gt; 0 {
          timeLeft = endTime?.timeIntervalSinceNow ?? 0
          timeLabel.text = timeLeft.time
      } else {
          timeLabel.text = &quot;00:00&quot;
          timer.invalidate()
      }
  }
  
  //-------------timer finish------------(extension for timer at bottom of file------
  </code></pre>
  <p>Extensions:</p>
  <pre><code>//extensions for timer
  extension TimeInterval {
      var time: String {
          return String(format:&quot;%02d:%02d&quot;, Int(self/60),  Int(ceil(truncatingRemainder(dividingBy: 60))) )
      }
  }
  extension Int {
      var degreesToRadians : CGFloat {
          return CGFloat(self) * .pi / 180
      }
  }
  </code></pre>
  <p>ViewDidload:</p>
  <pre><code>//for countdown timer: -------------
      view.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 = timeLeft
          // 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)
  </code></pre>
  <p><a href="https://i.stack.imgur.com/muCyb.png" rel="nofollow noreferrer"><img src="https://i.stack.imgur.com/muCyb.png" alt="enter image description here" /></a></p>