[iOS/UI] ํน์ ๋ถ๋ถ๋ง ํฌ๋ช ํ๊ฒ ๋ง๋ค๊ธฐ (feat. fillRule, evenOdd)
์๋
ํ์ธ์ Foma ์
๋๋ค!
์ค๋์ ํ๋ก์ ํธ ์งํ ์ค์ ํน์ ๋ถ๋ถ๋ง ํฌ๋ช ํ๊ฒ ํด์ ๊ทธ ๋ถ๋ถ๋ง ๋ณด์ด๊ฒ ํ๋ ๊ธฐ๋ฅ์ ๋ง๋๋ ๋ฒ์ ๋ํด ์ ๋ฆฌํด ๋ณด๋ ค๊ณ ํฉ๋๋ค.
๋ฐ๋ก ์์ํ ๊ฒ์~
Preview
Add a label
๋ฐฐ๊ฒฝ์ ๋ ์ด๋ธ์ ํ๋ ๋ฃ์ด ํฌ๋ช ํ์ง ์๋์ง ํ์ธํ๊ธฐ ์ฝ๊ฒ ๋ง๋ค์ด ์ฃผ๊ฒ ์ต๋๋ค.
let label = UILabel(frame: CGRect(x: view.center.x - 100, y: view.center.y - 100, width: 200, height: 200))
label.backgroundColor = .systemBlue
label.textColor = .white
label.font = UIFont.boldSystemFont(ofSize: 20)
label.text = "Fomagran"
label.textAlignment = .center
label.layer.cornerRadius = 100
label.layer.masksToBounds = true
view.addSubview(label)
์๋์ ๊ฐ์ด ๋ ์ด๋ธ์ด ์ถ๊ฐ๋ ๊ฑฐ์์.
Add a backgroundView
๋ฐํฌ๋ช ํ ๋ฐฐ๊ฒฝ์์ด ๋ backgroundView๋ฅผ ์ถ๊ฐํด ์ค๋๋ค.
let backgroundView = UIView(frame: view.frame)
backgroundView.backgroundColor = .black.withAlphaComponent(0.6)
view.addSubview(backgroundView)
์๋์ ๊ฐ์ด ๋ฐํฌ๋ช ํ ๋ทฐ๊ฐ ๋ ์ด๋ธ ์๋ฅผ ๋ฎ๊ฒ ์ฃ ?
Set a maskLayer's path
์์์ ๋ง๋ backgroundView์ mask๊ฐ ๋ CAShapeLayer๋ฅผ ๋ง๋ค์ด ์ค๊ฑฐ์์.
let maskLayer = CAShapeLayer()
์ ๋ ์ด์ด๋ฅผ ๋ง๋ ์ด์ ๋ ์ง์ UIBezierPath๋ฅผ ๊ทธ๋ ค ์ง์ ํ ์ ์๊ธฐ ๋๋ฌธ์ด์์.
์ด 2๊ฐ์ Path๋ฅผ ๊ทธ๋ ค์ค๊ฑด๋ฐ์.
ํ๋๋ backgroundView์ ๊ฐ์ ํฌ๊ธฐ์ ์์น์ ์๋ backgroundPath๋ฅผ ๋ง๋ค์ด ์ฃผ๊ณ ,
let backgroundPath = UIBezierPath(rect: view.frame)
ํ๋๋ ํฌ๋ช ํ ๋ถ๋ถ์ ๋ชจ์์ด ๋ transparentPath๋ฅผ ๊ทธ๋ ค์ค๊ฑฐ์์.
(ํน์ EasierPath๋ฅผ ๋ชจ๋ฅด์๋ ๋ถ๋ค์ ์ฌ๊ธฐ ์์ ํ์ธํด ์ฃผ์ธ์!)
let transparentPath = EasierPath(view.center.x-50,view.center.y-100)
transparentPath.right(100)
transparentPath.down(200)
transparentPath.left(100)
transparentPath.up(200)
backgroundPath์ transparentPath๋ฅผ ์ถ๊ฐํด ์ฃผ๊ณ , maskLayer์ path๋ฅผ backgroundPath๋ก ์ง์ ํด ์ค๋๋ค.
backgroundPath.append(transparentPath.path)
maskLayer.path = backgroundPath.cgPath
๊ทธ๋ฆฌ๊ณ backgroundView์ ๋ ์ด์ด์ mask๋ฅผ maskLayer๋ก ๋ฎ์ด์ฃผ์ธ์.
backgroundView.layer.mask = maskLayer
๊ทธ๋ฆฌ๊ณ ์คํ์์ผ ๋ณด๋ฉด? ์๋ฌด ์ผ๋ ์ผ์ด๋์ง ์์ต๋๋ค.
์๋ํ๋ฉด backgroundPath์ transparenthPath๊ฐ ๊ฒน์ณ์ ธ ์๊ธฐ ๋๋ฌธ์ด์์.
Set a fillRule to evenOdd
์์์ backgroundPath์ transparentPath๊ฐ ๊ฒน์ณ์ ธ ์๋ค๊ณ ํ์ฃ ?
ํน์ ๊ฒฝ๋ก๊ฐ ๊ฒน์ณ์ง๋ ๊ณณ์ ์ ์ธํ๊ณ ์์ด ์ฑ์์ง ์ ์๊ฒ ํ ์ ์๋๋ฐ์.
๋ฐ๋ก fillRule์ .evenOdd๋ก ํด์ฃผ๋ ๊ฒ์ ๋๋ค.
maskLayer.path = backgroundPath.cgPath
maskLayer.fillRule = .evenOdd
backgroundView.layer.mask = maskLayer
๊ทธ๋ฆฌ๊ณ ์คํํด ๋ณด๋ฉด ์ฐ๋ฆฌ๊ฐ ์ํ๋ ๋ชจ์๋ง ํฌ๋ช ํ๊ฒ ๋ฉ๋๋ค.
What is a evenOdd?
๊ทธ๋ ๋ค๋ฉด fillRule์ evenOdd๋ ๋ฌด์์ผ๊น์?
๊ณต์ ๋ฌธ์์ evenOdd๋ฅผ ์๋์ ๊ฐ์ด ์ค๋ช ํ๊ณ ์์ด์.
๊ฐ๋จํ๊ฒ ํด์ํ๋ฉด ๊ฒน์น๋ ๋ถ๋ถ์ ์ด ์๋ฅผ ์ธ๊ณ , ๋ง์ฝ ๊ทธ ์๊ฐ ์ง์์ด๋ฉด ์ธ๋ถ๋ฅผ ์๋ฏธํฉ๋๋ค.
๊ทธ๋ฆฌ๊ณ ๋ง์ฝ ์ด ์๊ฐ ํ์์ด๋ฉด ๋ด๋ถ๋ฅผ ๋ปํ๋ฉฐ ํด๋น ์์ญ์ ์ฑ์์ผ ํ๋ ๊ฒ์ธ๋ฐ์.
์ด๋ ๊ฒ ๋งํ๋ ์ข ์ดํด๊ฐ ํ๋์ค ๊ฒ ๊ฐ์ ์ฝ๊ฒ ์ค๋ช ๋๋ฆฌ๋ฉด ์๋์ ๊ฐ์ด A,B๊ฐ ์๊ณ ๊ฐ ์ง์ ๋ง๋ค ๊ฒน์น ๋ถ๋ถ(1)์ ๋ํ๋ ๋๋ค.
๋ง์ฝ ๋ A,B ๊ตฌ๊ฐ์ด ๊ฒน์น๋ค๋ฉด ์๋์ ๊ฐ์ด ๊ฒน์น ๋ถ๋ถ์ด 2๊ฐ ๋๊ณ ํด๋น ๋ถ๋ถ์ ์ง์๊ฐ ๋ฉ๋๋ค.
๊ณ ๋ก ์ง์๊ฐ ๋ ๋ถ๋ถ์ ์ธ๋ถ ์์ญ์ผ๋ก ์๋ฏธํ์ฌ ์ฑ์ฐ์ง ์์๋ ๋๋ ๊ท์น์ ๋ปํ๋ ๊ฒ ์ ๋๋ค.
์ค๋์ ์ด๋ ๊ฒ CAShapeLayer์ ์ฑ์ฐ๊ธฐ ๊ท์น(fillRule)์ oddEven์ ์ด์ฉํ์ฌ ์ํ๋ ๋ถ๋ถ๋ง ํฌ๋ช ํ๊ฒ ๋ง๋๋ ๋ฒ์ ๋ํด์ ์์ ๋ณด์์ต๋๋ค.
ํน์๋ผ๋ ๊ถ๊ธํ์ ์ ์ด๋ ํ๋ฆฐ ์ ์ด ์๋ค๋ฉด ๋๊ธ๋ก ์๋ ค์ฃผ์ธ์!