美文网首页
【Swift】自制带车进度条(横着跑的)

【Swift】自制带车进度条(横着跑的)

作者: 哗啦啦啦呃 | 来源:发表于2023-02-08 16:36 被阅读0次

    进度条样式:


    image.png

    为了方便添加属性,用了@IBDesignable关键字

    @IBDesignable class FLJProgressView: UIView {
    //添加进度条相应参数设置
    struct Constant {
            //进度条宽度默认
            static var lineWidth: CGFloat = 40
            //进度槽颜色
            static let trackColor = "#a8cff6".color!
            //进度条颜色
            static let progressColoar = "#2988e6".color!
        }
         
        //进度槽
        let trackLayer = CAShapeLayer()
        //进度条
        let progressLayer = CAShapeLayer()
        //进度条路径
        let path = UIBezierPath()
        //头部圆点
        var dot:UIView = UIView()
        //头部图片
        var arrow = UIImageView(image: UIImage(named: "car"))
        var progressInt = UILabel()
        
        //进度条中点
        var progressCenter:CGPoint {
            get{
                return CGPoint(x: 4, y: 0)
            }
        }
        //当前进度
        @IBInspectable var progress: Int = 0 {
            didSet {
                if progress > 100 {
                    progress = 100
                }else if progress < 0 {
                    progress = 0
                }
            }
        }
    required init?(coder aDecoder: NSCoder) {
            super.init(coder: aDecoder)
        }
         
        override init(frame: CGRect) {
            super.init(frame: frame)
        }
    override func draw(_ rect: CGRect) {
            //获取整个进度条路径
            path.move(to: CGPoint(x: 0, y: 0))
            path.addLine(to: CGPoint(x: bounds.size.width, y: 0))
    //        if bounds.size.height > Constant.lineWidth {
    //            Constant.lineWidth = bounds.size.height
    //        }
            
            //绘制进度槽
            trackLayer.frame = bounds
            trackLayer.fillColor = UIColor.clear.cgColor
            trackLayer.strokeColor = Constant.trackColor.cgColor
            trackLayer.lineWidth = Constant.lineWidth*2
            trackLayer.path = path.cgPath
            trackLayer.masksToBounds = true
            trackLayer.cornerRadius = 10
            layer.addSublayer(trackLayer)
             
            //绘制进度条
            progressLayer.frame = bounds
            progressLayer.fillColor = UIColor.clear.cgColor
            progressLayer.strokeColor = Constant.progressColoar.cgColor
            progressLayer.lineWidth = Constant.lineWidth*2
            progressLayer.path = path.cgPath
            progressLayer.strokeStart = 0
            progressLayer.strokeEnd = CGFloat(progress)/100.0
            progressLayer.masksToBounds = true
            progressLayer.cornerRadius = 10
            layer.addSublayer(progressLayer)
            
            //绘制进度条头部圆点
            dot = UIView(frame:CGRect(x: 0, y: 20, width: Constant.lineWidth,
                                      height: Constant.lineWidth))
            let dotPath = UIBezierPath(ovalIn:
                CGRect(x: 0,y: 20, width: Constant.lineWidth, height: Constant.lineWidth)).cgPath
            let arc = CAShapeLayer()
            arc.lineWidth = 0
            arc.path = dotPath
            arc.strokeStart = 0
            arc.strokeEnd = 1
            arc.strokeColor = Constant.progressColoar.cgColor
            arc.fillColor = Constant.progressColoar.cgColor
            arc.shadowColor = UIColor.black.cgColor
            arc.shadowRadius = 5.0
            arc.shadowOpacity = 0.5
            arc.shadowOffset = CGSize.zero
            dot.layer.addSublayer(arc)
            
            //圆点中添加图片
            arrow.frame = CGRect(x: -15, y: -20, width: Constant.lineWidth+30, height: Constant.lineWidth)
            dot.addSubview(arrow)
            
            // 远点中添加数字
            progressInt.frame.size = CGSize(width: Constant.lineWidth, height: Constant.lineWidth)
            progressInt.text = "\(progress)" + "%"
            progressInt.textColor = .black
            progressInt.textAlignment = .center
    //        dot.addSubview(progressInt)
            
            dot.layer.position = calcCircleCoordinateWithCenter(progressCenter, angle: CGFloat(progress))
            addSubview(dot)
            dot.isHidden = true
        }
    //设置进度(可以设置是否播放动画)
        func setProgress(_ pro: Int,animated anim: Bool) {
            setProgress(pro, animated: anim, withDuration: 0.1)
        }
         
        //设置进度(可以设置是否播放动画,以及动画时间)
        func setProgress(_ pro: Int,animated anim: Bool, withDuration duration: Double) {
            let oldProgress = progress
            progress = pro
            if pro >= 1,dot != nil {
                dot.isHidden = false
            }
            //进度条动画
            CATransaction.begin()
            CATransaction.setDisableActions(!anim)
            CATransaction.setAnimationTimingFunction(CAMediaTimingFunction(name:CAMediaTimingFunctionName.easeInEaseOut))
            CATransaction.setAnimationDuration(duration)
            progressLayer.strokeEnd = CGFloat(progress)/100.0
            CATransaction.commit()
            
            //头部圆点动画
            let startX = CGFloat(Double(oldProgress))/100*bounds.size.width
            let endX = CGFloat(Double(progress))/100*bounds.size.width
            let path2 = CGMutablePath()
            path2.move(to: CGPoint(x: startX, y: 0), transform: transform)
            path2.addLine(to: CGPoint(x: endX, y: 0), transform: transform)
             
            let orbit = CAKeyframeAnimation(keyPath:"position")
            orbit.duration = duration
            orbit.path = path2
            orbit.calculationMode = CAAnimationCalculationMode.paced
            orbit.timingFunction =
            CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut)
            orbit.rotationMode = CAAnimationRotationMode.rotateAuto
            orbit.isRemovedOnCompletion = false
            orbit.fillMode = CAMediaTimingFillMode.forwards
            dot.layer.add(orbit,forKey:"Move")
            progressInt.text = "\(progress)" + "%"
        }
         
        //将角度转为弧度
    //    fileprivate func angleToRadian(_ angle: Double)->CGFloat {
    //        return CGFloat(angle/Double(180.0) * M_PI)
    //    }
        //计算圆弧上点的坐标
        func calcCircleCoordinateWithCenter(_ center:CGPoint, angle:CGFloat)
            -> CGPoint {
            let x2 = angle*bounds.size.width/100
            return CGPoint(x: center.x+x2, y: center.y);
        }
    }
    

    通过setProgress()在控制进度的地方设置进度条的进度。

    相关文章

      网友评论

          本文标题:【Swift】自制带车进度条(横着跑的)

          本文链接:https://www.haomeiwen.com/subject/tdbqkdtx.html