Old_SWIFT(221012)/기술이야기

파이차트그리기(2) + UIBezierPath + 시간표그리기

KataRN 2021. 12. 14. 16:47
반응형
let centerCircle = UIBezierPath(arcCenter: center, radius: 60, startAngle: 0, endAngle: (360 * .pi) / 180, clockwise: true)
UIColor.gray.set()
centerCircle.fill()

안녕하세요.

KataRN입니다.

 

파이차트 그리기 이어서 진행하겠습니다.

 

앞에 내용도 중요하니 순서대로 글 읽어주시면 감사합니다.(조회수 +1 올려줘...)

파이차트 그리기(1) 링크 입니다.

https://katarnios.tistory.com/19

 

파이차트그리기(1) + UIBezierPath + 도형그리기

안녕하세요. KataRN입니다. 오늘은 선긋는 방법부터 최종적으로 원그래프(파이차트)까지 그려보려고 합니다. 원그래프는 보통 수량을 한눈에 보기위해 원을 이용해서 사용하며 도넛모양으로 생

katarnios.tistory.com

 

저번시간에 케이크를 잘못만들었었는데...

저희가 상상했던 모양은 이런건데...

웬 펩시맨이 나왓어요...(펩시맨.. 알죠?..ㅎㅎ)

그 이유에 대해 생각해봅시다.

 

저희가 UIBezierPath를 이용해서 도형을 만들었죠?

삼각형을 만들때 가장 필요했던것은? 꼭지점입니다. 꼭지점이 2개면 선분 3개면 삼각형 4개면 사각형입니다.

점에서 점으로 잇는 코드만 써도 도형이 만들어지죠.

 

위의 그림은 호를 그리고 그냥 채웠으며 반전된 호를 그리고 또 채웠으니 저렇게 나오는게 당연한겁니다.

그렇다면? 꼭지점을 하나 찍고 호와 연결을 해서 색을 칠하면 될것같군요.

확신은 없어요. 그냥 해보는거지...(저는 여러번의 시행착오를 거치지만 마치 한번에 하는것처럼 연기하는겁니다...ㅎㅎ)

 

let path = UIBezierPath()
let center = CGPoint(x: rect.midY, y: rect.midX)
path.move(to: center)
path.addArc(withCenter: center, radius: 75, startAngle: (45 * .pi) / 180, endAngle: (135 * .pi) / 180, clockwise: true)
path.stroke()

홀리몰리~ 과카몰리! 로보카폴리! 롤리폴리!

드디어 점과 호를 이었습니다. 이제 나머지 이으려면 어떻게 하면 되는지 아시죠?

close()를 하시면 선으로 만든 도형이 되는거고 fill을 하면 안에 색도 채우는거죠.

let path = UIBezierPath()
let center = CGPoint(x: rect.midY, y: rect.midX)
path.move(to: center)
path.addArc(withCenter: center, radius: 75, startAngle: (45 * .pi) / 180, endAngle: (135 * .pi) / 180, clockwise: true)
UIColor.systemYellow.setFill()
path.lineWidth = 5

path.fill()
//선 안을 채운다.
//path.close()
//나머지 점과 점을 닫는다.
        
path.stroke()

제가 일부러 path.close()를 주석처리 했습니다.

왜냐하면 close를 안하면 왼쪽 검은색 선이 빠진게 보이실겁니다.

이 차이를 설명드리고싶었습니다. close를 하면 선으로 전부 감싸게됩니다.

어라? 저기서 흰선으로 놓고 반전된곳도 추가하면 파이차트가 되네?ㅋㅋㅋㅋㅋㅋ

근데 평생 2개뿐인 차트밖에 못만들겠죠....ㅠ

기왕하는거 완벽하게 해봅시다.

 

우선 시간표부터 만들어봅시다.

4가지정도로 영역을 나누고 비율과 색상을 준비할께요. 

let values: [CGFloat] = [10, 20, 30, 40]
let total = values.reduce(0,+)
let colors = [UIColor.systemYellow, UIColor.systemGreen, UIColor.systemBlue, UIColor.systemRed]

(reduce함수 모르시면 아래 링크 참고)

https://katarnios.tistory.com/12

 

<Reduce>함수 더하기 추론(조금...)

안녕하세요. KataRN입니다. 오늘은 Reduce 함수에 대해 알아보겠습니다.(이번엔 추론도 더해서 알아보겠습니다.) reduce 번역하면 "줄이다, 감소하다" 입니다. 하지만 이 함수는 덧셈 함수라고 할 수

katarnios.tistory.com

 

그리고 아래 표를 보시면 시작점이 3시방향이죠? 이걸 12시 방향으로 바꿔보겠습니다.

 

var startAngle: CGFloat = (-(.pi) / 2)
var endAngle: CGFload = 0.0

 

이제 기본 준비가 끝났습니다.

위에서 만들어준 비율이 담긴 배열을 통해 그래프를 그려보겠습니다.

let center = CGPoint(x: rect.midY, y: rect.midX)
let values: [CGFloat] = [10, 20, 30, 40]
let colors = [UIColor.systemYellow, UIColor.systemGreen, UIColor.systemBlue, UIColor.systemRed]
let total = values.reduce(0, +)
var startAngle: CGFloat = (-(.pi) / 2)
var endAngle: CGFloat = 0.0
        
values.enumerated().forEach { (index, value) in
    endAngle = (value / total) * (.pi * 2)
    print("(value / total) : \((value / total))")
    let path = UIBezierPath()
    path.move(to: center)
    path.addArc(withCenter: center, radius: 100, startAngle: startAngle, endAngle: startAngle + endAngle, clockwise: true)
    colors[index].set()
    path.fill()
    startAngle += endAngle
}

 

잠깐?

 

enumerated() 함수 모른다구요? 다녀와요~

https://katarnios.tistory.com/7

 

<enumarated> 함수

안녕하세요. KataRN입니다. 저번시간에 배운 zip함수 기억하십니까? Array와 관련된 함수 중 하나인데 zip함수에서 내용이 너무 없던것 같아서 보충수업 들어갑니다. 오늘 배울 함수는 enumarated 함수

katarnios.tistory.com

 

모얔ㅋㅋㅋㅋㅋ 왜 만들고나니까 크롬같이 생겼지;;

자 시간표가 만들어졌습니다.

 

이제  파이차트 어떡하냐구요?ㅋㅋㅋ

이게 진짜 쉬움 가운데에 배경색과 같은색의 동그란 원을 넣으면 됨ㅋㅋㅋ

 

let centerCircle = UIBezierPath(arcCenter: center, radius: 60, startAngle: 0, endAngle: (360 * .pi) / 180, clockwise: true)
        UIColor.gray.set()
        centerCircle.fill()

 

음 만들어졌는데 뭔가... 뭔가 말로는 못하겠지만 뭔가 이상해...

모든회색을 흰색으로 바꾸고 영역간의 사이를 띄워야 이쁠것 같네요~

사이를 띄우는건 띄운것처럼 보이도록 경계선을 배경색으로 바꿔주면됩니다.

 

이 차이를 배우기 위해 저희는 글 초반부에 케이크 만들기를 했었죠? 그걸 응용해서 코드를 추가해줍니다.

path.lineWidth = 3
path.close()
path.stroke()

 

과연 결과는????

 

완벽 그자체..

 

후후 이로써 저희는 파이차트를 정복하였습니다.

사실 파이차트뿐만 아니라 저희는 어떤 그림을 그릴 수 있게 된겁니다.

다음에는 애니메이션을 추가해보겠습니다.

 

오늘도 긴글 읽어주셔서 감사합니다.

하단에 전체코드 추가해놓겠습니다.

 

 

이글은 Zedd님의 글을 보고 99% 참고하였습니다. (솔직히 Zedd님 글이 더 잘되어있습니다.)

-> 링크 : https://zeddios.tistory.com/823

 

iOS ) UIBezierPath (4) - Pie chart

안녕하세요 :) Zedd입니다. 벌써 4편이라니....정말 저는 글로 정리하면서..공부하는게 제일 잘 맞는것 같아요. 뭔가ㅎ...뭔가 성장한 느낌이 드는군.. 오늘은 뭘 해볼거냐면... ㅇ저번 3편에서 원을

zeddios.tistory.com

 

import UIKit

class ViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let view = testView(frame: CGRect(x: 0, y: 0, width: 300, height: 300))
        view.center = self.view.center
        view.backgroundColor = .white
        self.view.addSubview(view)
    }


}

class testView: UIView {
    
    override func draw(_ rect: CGRect) {
        
        let center = CGPoint(x: rect.midY, y: rect.midX)
        let values: [CGFloat] = [10, 20, 30, 40]
        let colors = [UIColor.systemYellow, UIColor.systemGreen, UIColor.systemBlue, UIColor.systemRed]
        let total = values.reduce(0, +)
        var startAngle: CGFloat = (-(.pi) / 2)
        var endAngle: CGFloat = 0.0
        
        values.enumerated().forEach { (index, value) in
            endAngle = (value / total) * (.pi * 2)
            print("(value / total) : \((value / total))")
            let path = UIBezierPath()
            path.move(to: center)
            path.addArc(withCenter: center, radius: 100, startAngle: startAngle, endAngle: startAngle + endAngle, clockwise: true)
            colors[index].set()
            path.fill()
            startAngle += endAngle
            
            path.lineWidth = 3
            path.close()
            UIColor.white.set()
            path.stroke()
        }
        
        let centerCircle = UIBezierPath(arcCenter: center, radius: 60, startAngle: 0, endAngle: (360 * .pi) / 180, clockwise: true)
        UIColor.white.set()
        centerCircle.fill()
    }
}

 

 

 

 

반응형