๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ
๐ŸŽ iOS/UI

[iOS/UI] UIBezierPath ์•ˆ์„ Gradient ์ปฌ๋Ÿฌ๋กœ ์ฑ„์šฐ๊ธฐ (Fill a UIBezierPath with Gradient Color)

by Fomagran ๐Ÿ’ป 2022. 5. 2.
728x90
๋ฐ˜์‘ํ˜•

์•ˆ๋…•ํ•˜์„ธ์š” Foma๐Ÿ’ป ์ž…๋‹ˆ๋‹ค!

 

์˜ค๋Š˜์€ UIBezierPath ์•ˆ์„ Gradient ์ปฌ๋Ÿฌ๋กœ ์ฑ„์šฐ๋Š” ๋ฐฉ๋ฒ•์— ๋Œ€ํ•ด์„œ ์•Œ์•„๋ณด๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

๋ฐ”๋กœ ์‹œ์ž‘ํ• ๊ฒŒ์š”~


TestView

 

๋ทฐ๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ์ดˆ๊ธฐํ™” ํ•ด์ค๋‹ˆ๋‹ค.

 

class TestView: UIView {
    
    override init(frame: CGRect) {
        super.init(frame: frame)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    override func draw(_ rect: CGRect) {
       
    }
}

UIBezierPath

 

์ด์ œ UIBezierPath๋ฅผ draw ๋ฉ”์„œ๋“œ ์•ˆ์— ๊ทธ๋ ค๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

 

ํƒ€์›ํ˜• ๊ฒฝ๋กœ๋ฅผ ์•„๋ž˜์™€ ๊ฐ™์ด ์ƒ์„ฑํ•ด ์ค๋‹ˆ๋‹ค.

 

  let path:UIBezierPath = UIBezierPath(ovalIn: CGRect(x: bounds.midX-50, y:bounds.midY-50, width: 100, height: 200))

CGGradient

 

UIBezierPath์— ๊ทธ๋ ˆ๋””์–ธํŠธ ์ƒ‰์ƒ์„ ์ž…ํžˆ๊ธฐ ์œ„ํ•ด์„  CGGradient ๊ฐ์ฒด๋ฅผ ์ด์šฉํ•ด์•ผ ํ•˜๋Š”๋ฐ์š”.

 

 

์ด ๊ฐ์ฒด์—๋Š” 3๊ฐ€์ง€ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

 

 

1. ๊ทธ๋ ˆ๋””์–ธํŠธ ์ปฌ๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•  ๊ณต๊ฐ„

 

๊ทธ๋ ˆ๋””์–ธํŠธ ์ปฌ๋Ÿฌ๋ฅผ ์‚ฌ์šฉํ•  ๊ณต๊ฐ„์€ CGColorSpace๋ผ๋Š” ํด๋ž˜์Šค๋ฅผ ์ด์šฉํ•˜๋Š”๋ฐ์š”.

 

์ด๊ฒƒ์€ ํ™”๋ฉด์— ํ‘œ์‹œ๋˜๋Š” ์ƒ‰์ƒ๊ฐ’์„ ํ•ด์„ํ•˜๋Š” ํด๋ž˜์Šค์ž…๋‹ˆ๋‹ค.

 

 

ํฌ๊ฒŒ๋Š” RGB ์ƒ‰์œผ๋กœ ํ•ด์„ํ•  ๊ฒƒ์ธ์ง€, Gray๋กœ ํ•ด์„ํ•  ๊ฒƒ์ธ์ง€, CMYK๋กœ ํ•ด์„ํ•  ๊ฒƒ์ธ์ง€ ๋“ฑ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

์ด๋ฒˆ์—” ์ €๋Š” ํ•ด๋‹น ๋””๋ฐ”์ด์Šค์˜ RGB ์ƒ‰์ƒ ๊ณต๊ฐ„์„ ์‚ฌ์šฉํ•˜๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

let colorSpace = CGColorSpaceCreateDeviceRGB()

 

2. ๊ทธ๋ ˆ๋””์–ธํŠธ ์ปฌ๋Ÿฌ๋ฅผ ์ด๋ฃฐ ์ƒ‰๋“ค

 

๋ง ๊ทธ๋ž˜๋„ ๊ทธ๋ ˆ๋””์–ธํŠธ ์ปฌ๋Ÿฌ๋ฅผ ์ด๋ฃฐ ์ƒ‰๋“ค์„ ์ •ํ•ด์ค๋‹ˆ๋‹ค.

 

์ €๋Š” ์•„๋ž˜์™€ ๊ฐ™์ด ๋นจ๊ฐ„์ƒ‰๊ณผ ํŒŒ๋ž€์ƒ‰์„ ์ด์šฉํ•ด ๊ทธ๋ ˆ๋””์–ธํŠธ ์ปฌ๋Ÿฌ๋ฅผ ๊ตฌ์„ฑํ•˜๋„๋ก ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

let gradientColors:[CGColor] = [UIColor.red.cgColor,UIColor.blue.cgColor]

 

3. ๊ทธ๋ ˆ๋””์–ธํŠธ ์ปฌ๋Ÿฌ์˜ ์œ„์น˜๋“ค

 

๋งˆ์ง€๋ง‰์œผ๋กœ ๊ทธ๋ ˆ๋””์–ธํŠธ ์ปฌ๋Ÿฌ์˜ ์œ„์น˜๋ฅผ ์ •ํ•ด์ค˜์•ผ ํ•˜๋Š”๋ฐ์š”.

 

์ƒ‰๋“ค์ด ์–ด๋Š ์œ„์น˜์— ์ง€์ •๋  ๊ฒƒ์ธ์ง€๋ฅผ 0๊ณผ 1์„ ์‚ฌ์šฉํ•ด ๋‚˜ํƒ€๋‚ด ์ค๋‹ˆ๋‹ค. (ํ˜•์€ ๋ฐ˜๋“œ์‹œ CGFloat์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.)

 

์•„๋ž˜ ์‚ฌ์ง„์—์„œ ๊ฐ€์žฅ ์™ผ์ชฝ์ด [1.0,0.0] ๊ฐ€์šด๋ฐ๊ฐ€ [0.0,1.0] ์˜ค๋ฅธ์ชฝ์ด [0.5,0.5]๋ฅผ ์ ์šฉํ•œ ๊ฒฐ๊ณผ์ž…๋‹ˆ๋‹ค.

 

 

์ €๋Š” ์ปฌ๋Ÿฌ ์œ„์น˜๋ฅผ [0.0,1.0] ์œผ๋กœ ์ง€์ •ํ•˜๊ฒ ์Šต๋‹ˆ๋‹ค.

 

let colorLocations: [CGFloat] = [0.0,1.0]

 

์ด๋ ‡๊ฒŒ 3๊ฐ€์ง€ ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ๋ชจ๋‘ ์„ค์ •ํ–ˆ๋‹ค๋ฉด CGGradient ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ์ค˜์•ผ๊ฒ ์ฃ ?

 

์•„๋ž˜์™€ ๊ฐ™์ด ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค์–ด ์ค๋‹ˆ๋‹ค.

 

  let cgGradientColor = CGGradient(colorsSpace: colorSpace, colors: gradientColors as CFArray, locations:colorLocations)!

CGContext

 

์œ„์—์„œ UIBezierPath์™€ CGGradient๋ฅผ ์ƒ์„ฑํ•ด ์ฃผ์—ˆ์ฃ ?

 

๊ทธ๋ ‡๋‹ค๋ฉด ๋ณธ๊ฒฉ์ ์œผ๋กœ ํ•ด๋‹น ์ •๋ณด๋ฅผ "๊ทธ๋ฆฌ๊ธฐ" ์‹œ์ž‘ํ•ด์•ผ ํ•˜๋Š”๋ฐ์š”.

 

Core Graphics์—์„  2D๋กœ ๋ฌด์—‡์ธ๊ฐ€๋ฅผ ๊ทธ๋ฆฌ๊ธฐ ์œ„ํ•ด์„  CGContext๋ฅผ ์ง€์ •ํ•ด ์ค˜์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

 

์‰ฝ๊ฒŒ ํ˜„์žฌ ๊ทธ๋ž˜ํ”ฝ์— ๋งž๊ฒŒ ์ปจํ…์ŠคํŠธ๋ฅผ ์ง€์ •ํ•ด ์ค„ ์ˆ˜ ์žˆ๋Š” ๋ฉ”์„œ๋“œ๊ฐ€ ์กด์žฌํ•˜๋Š”๋ฐ

 

๋ฐ”๋กœ "UIGraphicsGetCurrentContext()"์ž…๋‹ˆ๋‹ค.

 

ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด์„œ ํ˜„์žฌ ์ปจํ…์ŠคํŠธ๋ฅผ ์•Œ์•„๋‚ด์–ด ์„ธํŒ…ํ•ด์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

 

let context = UIGraphicsGetCurrentContext()!

 

์ด์ œ ์œ„ ์ปจํ…์ŠคํŠธ์— ๋ณธ๊ฒฉ์ ์œผ๋กœ ์–ด๋–ค ์‹์œผ๋กœ ๊ทธ๋ฆด ๊ฒƒ์ธ์ง€๋ฅผ ๋ช‡ ๊ฐ€์ง€ ์ž‘์„ฑํ•ด ์ฃผ์–ด์•ผ ํ•˜๋Š”๋ฐ์š”.

 

1. ๊ฒฝ๋กœ ์ถ”๊ฐ€ํ•˜๊ธฐ

 

์œ„์—์„œ ๋งŒ๋“  UIBezierPath ๊ฒฝ๋กœ๋ฅผ ํ˜„์žฌ ์ปจํ…์ŠคํŠธ์— ์ถ”๊ฐ€ํ•ด ์ค๋‹ˆ๋‹ค.

 

context.addPath(path.cgPath)

 

2. ๊ฒฝ๋กœ ์ง€์ •ํ•ด ์ฃผ๊ธฐ

 

์œ„์—์„œ ์ถ”๊ฐ€ํ•ด์ค€ ๊ฒฝ๋กœ๋ฅผ clip() ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด์„œ ํด๋ฆฌํ•‘ํ•  ๊ฒฝ๋กœ๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

 

 

context.clip()

 

3. ๊ฒฝ๋กœ์˜ ์„  ๋‘๊ป˜ ์ •ํ•˜๊ธฐ

 

๊ฒฝ๋กœ์˜ ์„  ๋‘๊ป˜๋ฅผ ์–ด๋Š ์ •๋„๋กœ ํ•  ๊ฒƒ์ธ์ง€ ์„ธํŒ…ํ•ด ์ค๋‹ˆ๋‹ค.

 

context.setLineWidth(10)

 

4. ๊ฒฝ๋กœ๋ฅผ stroke๋กœ ๋Œ€์ฒดํ•˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

 

UIBezierPath๋ฅผ ๊ทธ๋ฆฌ๋Š” stroke๋ฅผ ๊ฒฝ๋กœ๋กœ ์ง€์ •ํ•ด ์ค๋‹ˆ๋‹ค.

 

context.replacePathWithStrokedPath()

 

๋งŒ์•ฝ ์ง€์ •ํ•˜์ง€ ์•Š๋Š”๋‹ค๋ฉด UIBezierPath ์•ˆ์— ๊ทธ๋ ˆ๋””์–ธํŠธ ์ƒ‰์ด fill๋กœ ๋ฉ๋‹ˆ๋‹ค.

 

์™ผ์ชฝ์ด ํ•ด๋‹น ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•œ ๊ฒƒ์ด๊ณ  ์˜ค๋ฅธ์ชฝ์ด ์ž‘์„ฑํ•˜์ง€ ์•Š์•˜์„ ๊ฒฝ์šฐ์ž…๋‹ˆ๋‹ค.

 

 

6. ๊ทธ๋ ˆ๋””์–ธํŠธ ๊ทธ๋ ค์ฃผ๊ธฐ

 

๋งˆ์ง€๋ง‰์œผ๋กœ ํ˜„์žฌ ์ปจํ…์ŠคํŠธ์— ์œ„์— ์„ธํŒ…ํ–ˆ๋˜ CGGradient ์ธ์Šคํ„ด์Šค์™€ ์‹œ์ž‘ ์ง€์ ๊ณผ ๋ ์ง€์ ์„ ์ง€์ •ํ•ด ์ค๋‹ˆ๋‹ค.

 

context.drawLinearGradient(cgGradientColor, start: CGPoint(x: 0, y: 0), end: CGPoint(x: frame.width, y:frame.height), options: [])

 

๊ทธ๋ ˆ๋””์–ธํŠธ๋ฅผ ๊ทธ๋ฆฌ๋Š” ์˜ต์…˜์€ Linear๋ฟ๋งŒ ์•„๋‹ˆ๋ผ Radical ๋ฐฉ์‹์œผ๋กœ๋„ ๊ทธ๋ฆด ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 


TestViewController

 

TestView๋ฅผ ์œ„์™€ ๊ฐ™์ด ์„ธํŒ…ํ•ด์ฃผ๊ณ  TestViewController์—์„œ ํ…Œ์ŠคํŠธํ•˜๊ฒŒ ๋˜๋ฉด

 

class TestViewController: UIViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        let testView:TestView = TestView(frame:view.frame)
        testView.backgroundColor = .white
        view.addSubview(testView)
    }
}

 

์•„๋ž˜์™€ ๊ฐ™์ด ์ง€์ •ํ•œ UIBezierPath๋Œ€๋กœ Gradient ์ปฌ๋Ÿฌ๊ฐ€ ์ฑ„์›Œ์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.


Source Code

 

 

728x90
๋ฐ˜์‘ํ˜•

๋Œ“๊ธ€