ARCHIVES

태그

신고하기

상단 메뉴 페이지

기본 콘텐츠로 건너뛰기

[ios] Gauge 그리기, UIBezierPath 사용

프로젝트에서 게이지를 그려야 할 필요성이 생겼다.

별로 어렵지 않을거 같아서, 직접 만들어 본다.

참고한 URL 링크는 Zedd님 블로그, 없는게 없네;;

Zedd : iOS ) UIBezierPath (1)
 : 중학생도 알수있는 베지에 곡선 : https://blog.coderifleman.com/2016/12/30/bezier-curves/
 : UIBezierPath 사용법

 : close 는 옵션이다. 넣으면 도형, 안넣으면 선으로 됨.
 : path.lineWidth
 : path.lineJoinStyle
 : setLineDash

 : 삼각형 그리기
 : 원 그리기
 ; roundedRect로 사각형을 원처럼 보일 수도 있다.
 : 호 그리기

 : 제대로 호 그리기
 : startAngle 위치 알기
 : endAngle 위치 알기, .pi는 180도닌까 360도는 .pi * 2 이다.
 : 일단 도넛 내부는 백그라운드로 그리기.
 : 에니메이션을 하려면 CALayer를 사용, CAShapeLayer로 그려야 에니메이션이 된다.
 : 급...CA 즉 core animation 글이 됨.
 : path.cgPath를 사용한다.


대충 화면 변환 체크까지 해서 완료.


class HKGaugeView: UIView {

    

    private var imageView: UIImageView?

    private var userChage: Bool = false

    private var userAngle: CGFloat = 0

    

    var gaugeBgColor: UIColor {

        self.backgroundColor ?? UIColor.black

    }

        

    // override var backgroundColor: UIColor? = UIColor.black

    override init(frame: CGRect) {

         super.init(frame: frame)

        commonInit()

    }


    required init?(coder aDecoder: NSCoder) {

        super.init(coder: aDecoder)

        commonInit()

    }

    

    private func commonInit() {

        self.clipsToBounds = true

        

        let image = UIImage(named: "pen")

        imageView = UIImageView(image: image!)

        self.addSubview(imageView!)

    }


    override func layoutSublayers(of layer: CALayer) {

        super.layoutSublayers(of: layer)

        if !userChage {

            // 사이즈 변경

            self.imageView?.transform = .identity // 회전 원복

            let imageWidth = self.bounds.width / 5

            imageView?.frame = CGRect(x: 0, y: 0, width: imageWidth, height: imageWidth*3)

            if userAngle != 0 {

                self.imageView?.transform = CGAffineTransform(rotationAngle: .pi * userAngle / 200) // 다시 회전

            }

            // 중앙값 변경

            let rect: CGRect = self.bounds

            let center = CGPoint(x: rect.midX, y: rect.maxY - 10)

            imageView?.center = center

        }

    }


    // Only override draw() if you perform custom drawing.

    // An empty implementation adversely affects performance during animation.

    override func draw(_ rect: CGRect) {

        //중심값

        let center = CGPoint(x: rect.midX, y: rect.maxY - 10)

        // 호의 갯수, 왼쪽부터 시작한다.

        let colors: [UIColor] = [.red, .green, .red, .gray]

        let values: [CGFloat] = [90, 90, 90, 90]

        let total = values.reduce(0, +)

        // 반지름은 가로길이의 절반

        let radius = rect.width / 2

        let radiusDoughnut = rect.width / 4

        // 호를 그리는 변수

        var startAngle: CGFloat = ((.pi) * 3 / 4)

        var endAngle: CGFloat = 0.0

        

        values.enumerated().forEach { index, value in

            endAngle = (value / total) * (.pi * 2)

            

            let path = UIBezierPath()

            path.move(to: center)

            path.addArc(withCenter: center,

                        radius: radius,

                        startAngle: startAngle,

                        endAngle: startAngle + endAngle,

                        clockwise: true)

            // UIColor.lightGray.set()

            colors[index].set()

            path.fill()

            path.close()

            self.gaugeBgColor.set()

            path.lineWidth = 3

            path.stroke()

            startAngle += endAngle

        }

        // 배경색으로 덧그리기

        let path = UIBezierPath(arcCenter: center,

                                radius: radiusDoughnut,

                                startAngle: 0,

                                endAngle: 360,

                                clockwise: true)

        self.gaugeBgColor.set()

        path.fill()

        

        imageView?.center = center

    }


    open func gaugeBarSet(num: CGFloat) {

        userAngle = num

        userChage = true

        UIView.animate(withDuration: 0.5, animations: {

            if num == 0 {

                self.imageView?.transform = .identity

            }

            self.imageView?.transform = CGAffineTransform(rotationAngle: .pi * num / 200)

        }) { finished in

            self.userChage = false

        }

    }

}


댓글