代码之家  ›  专栏  ›  技术社区  ›  Midhun Narayan

使用CAShapelayer的循环计时器

  •  3
  • Midhun Narayan  · 技术社区  · 7 年前

    尝试为我的应用程序创建循环计时器,结果如下

    override func drawRect(rect: CGRect) {
    
        let context = UIGraphicsGetCurrentContext()
    
        let progressWidth: CGFloat = 10;
    
        let centerX = CGRectGetMidX(rect)
        let centerY = CGRectGetMidY(rect)
        let center: CGPoint = CGPointMake(CGRectGetMidX(rect), CGRectGetMidY(rect))
        let radius: CGFloat = rect.width / 2
    
    
        var circlePath = UIBezierPath(arcCenter: center, radius: radius, startAngle: CGFloat(0), endAngle:CGFloat(M_PI * 2), clockwise: true)
        let backgroundCircle = CAShapeLayer()
    
    
    
    
        backgroundCircle.path = circlePath.CGPath
        backgroundCircle.fillColor = backgroundCircleFillColor
        self.layer.addSublayer(backgroundCircle)
    
        circlePath = UIBezierPath(arcCenter: center, radius: radius-progressWidth/2, startAngle: -CGFloat(GLKMathDegreesToRadians(90)), endAngle:CGFloat(GLKMathDegreesToRadians(currentAngle)), clockwise: true)
        let progressCircle = CAShapeLayer()
        progressCircle.path = circlePath.CGPath
        progressCircle.lineWidth = progressWidth
        progressCircle.strokeColor = progressCircleStrokeColor
        progressCircle.fillColor = UIColor.clearColor().CGColor
        self.layer.addSublayer(progressCircle)
    
    
        let innerCirclePath = UIBezierPath(arcCenter: center, radius: radius-progressWidth, startAngle: CGFloat(0), endAngle:CGFloat(M_PI * 2), clockwise: true)
    
        let innerCircle = CAShapeLayer()
        innerCircle.path = innerCirclePath.CGPath
        innerCircle.fillColor = innerCircleFillColor
    
        self.layer.addSublayer(innerCircle)
    }
    
    1. 列表项目 以下是我的代码的输出:

    Here is the output got from my code

    本规范面临的主要问题有

    1. 画圆圈时手机发热
    2. 拉深半圈后溺水速度下降

    请帮我找一个替代方案

    3 回复  |  直到 7 年前
        1
  •  3
  •   Sharad Chauhan Muhammad Bilal Hussain    7 年前

    尝试以下操作:

    import UIKit
    
    class CircularProgressBar: UIView {
    
        let shapeLayer       = CAShapeLayer()
        let secondShapeLayer = CAShapeLayer()
        var circularPath: UIBezierPath?
    
        override init(frame: CGRect) {
            super.init(frame: frame)
            print("Frame: \(self.frame)")
            makeCircle()
        }
    
        required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
            makeCircle()
        }
    
        func makeCircle(){
            let circularPath = UIBezierPath(arcCenter: .zero, radius: self.bounds.width / 2, startAngle: 0, endAngle: 2 * CGFloat.pi, clockwise: true)
            shapeLayer.path = circularPath.cgPath
            shapeLayer.strokeColor = UIColor.orange.cgColor//UIColor.init(red: 0.0/255.0, green: 0.0/255.0, blue: 0.0/255.0, alpha: 1.0).cgColor
            shapeLayer.lineWidth = 5.0
            shapeLayer.fillColor = UIColor.clear.cgColor
            shapeLayer.lineCap = kCALineCapRound
            shapeLayer.strokeEnd = 0
            shapeLayer.position = self.center
            shapeLayer.transform = CATransform3DRotate(CATransform3DIdentity, -CGFloat.pi / 2, 0, 0, 1)
            self.layer.addSublayer(shapeLayer)
    
        }
    
    
        func showProgress(percent: Float){
            shapeLayer.strokeEnd = CGFloat(percent/100)
        }
    
    
    }
    

    采取行动 UIView 在里面 Storyboard 并将其添加为子视图。然后您可以使用 showProgress 作用

        2
  •  1
  •   clemens    7 年前

    不应在中添加层 drawRect: . 每次绘制视图时,都会添加一个图层。这就是为什么你的iPhone会受到影响,并且变得越来越慢、越来越热,这并不奇怪。您应该在中创建图层 viewDidLoad 或者创建视图的位置,并且不应在中修改它们 drawRect . 此方法为 只有 用于绘图,而不是其他。

        3
  •  0
  •   YohoMan    5 年前

    我就是这样做的,为我工作。我们需要两层,一层用于循环,另一层用于进度。

    private let circularProgressView = UIView()
    private let circleLayer = CAShapeLayer()
    private let progressLayer = CAShapeLayer()
    private var circularPath: UIBezierPath?
    
        private func setupCircularProgressBar() {
        circularPath = UIBezierPath(arcCenter: CGPoint(x: circularProgressView.frame.size.width / 2.0,
                                                       y: circularProgressView.frame.size.height / 2.0),
                                    radius: circularProgressView.bounds.width / 2, startAngle: -.pi / 2,
                                    endAngle: 3 * .pi / 2, clockwise: true)
        
        circleLayer.path = circularPath?.cgPath
        circleLayer.fillColor = UIColor.clear.cgColor
        circleLayer.lineCap = .round
        circleLayer.lineWidth = 5
        circleLayer.strokeColor = UIColor.darkGray.cgColor
        
        progressLayer.path = circularPath?.cgPath
        progressLayer.fillColor = UIColor.clear.cgColor
        progressLayer.lineCap = .round
        progressLayer.lineWidth = 3
        progressLayer.strokeEnd = 0
        progressLayer.strokeColor = UIColor.white.cgColor
        
        circularProgressView.layer.addSublayer(circleLayer)
        circularProgressView.layer.addSublayer(progressLayer)
    }
    
    private func animateCircularProgress(duration: TimeInterval) {
        let circularProgressAnimation = CABasicAnimation(keyPath: "strokeEnd")
        circularProgressAnimation.duration = duration
        circularProgressAnimation.toValue = 1
        circularProgressAnimation.fillMode = .forwards
        circularProgressAnimation.isRemovedOnCompletion = false
        progressLayer.add(circularProgressAnimation, forKey: "progressAnim")
    }
    

    用法非常简单,您只需使用时间间隔参数调用animateCircularProgress方法,如下所示,持续时间为5秒: animateCircularProgress(duration: 5)