오늘은 SwiftUI에서 뒤에가 빛나는 듯한 UI를 구성해볼까 합니다.
<결과물>
import SwiftUI
struct CustomButton: View {
var body: some View {
Button(action: {}) {
GeometryReader { geo in // <--
}
}
}
}
GeometryReader { geo in
ZStack {
}
}
Button(action: {}) {
...
}
.frame(height: 50)
var gradient1: [Color] = [
Color(red: 101/255, green: 134/255, blue: 1),
Color(red: 1, green: 64/255, blue: 80/255),
Color(red: 109/255, green: 1, blue: 185/255),
Color(red: 39.255, green: 232/255, blue: 1)
]
var body: some View {
Button(action: { }) {
GeometryReader() { geo in
ZStack {
AngularGradeint(
gradient: gradient1,
center: .center,
angle: .degrees(0)
)
}
}
}
}
공식문서상에는 정말 짧께 설명하고 있습니다.
네, 맞아요. 각도가 있는 그라데이션 객체입니다. 공식문서를 보시면서 이해하시는 것보다는, 색깔과 각도를 조절하시면서 이해하는게 더 빠를 것 같으니, 한 번 직접 만들어보고 파라미터의 값을 조정해보시는걸 추천합니다.
AngularGradient(
colors: gradient1,
center: .center,
angle: .degrees(8.0))
.blendMode(.overlay)
.blur(radius: 8.0)
.mask(
RoundedRectangle(cornerRadius: 16.0)
.frame(height: 50)
.frame(maxWidth: geo.size.width - 16)
.blur(radius: 8.0)
)
수식어에 대해서 하나씩 알아보겠습니다.
뷰를 겹쳐지는 뷰와 합성하기 위한 혼합 모드를 설정할때, 사용하라. 뭐 이런 뜻입니다.
의역을 보면, 뷰가 2개 이상인데 그 두 개를 혼합할 때, 설정해주면, 우리가 원하는 방식으로 섞어주는 듯 합니다.
공식예제를 보면 좀더 와닿겠네요.
struct Example: View {
var body: some View {
HStack {
Color.yellow.frame(width: 50, height: 50, alignment: .center)
Color.red.frame(width: 50, height: 50, alignment: .center)
.rotationEffect(.degrees(45))
.padding(-20)
// .blendMode(.colorBurn)
}
}
}
Color.red.frame(width: 50, height: 50, alignment: .center)
.rotationEffect(.degrees(45))
.padding(-20)
.blendMode(.colorBurn) // <--
colorBurn
이라는 블랜드모드는 겹쳐지지 않은 곳은 제거하는 특성이라고 합니다.저희는 겹쳐지는 Overlay라는 특성을 사용했습니다. overlay는 레이어들 중에서 가장 위에있는 레이어가 밝은 부분은 밝아집니다. 그리고 가장 아래에 있는 레이어의 어두운 부분은 어두워집니다. 즉, 광원효과처럼 뭔가 빛나는 효과에 적절하겠죠.
블러는 이름에서도 바로 느껴지듯, 흐릿하게 처리해주는 수식어입니다. 다만 가우시안 블러 라는게 좀 생소하시죠. 자세한 설명은 힘들지만, 가우스 함수로 만든 블러 연산을 한 블러처리입니다. 블러처리에 자주 사용되곤 합니다. CoreImage 단에서 CIFilter 필터에도 있는 필터 중 하나입니다.
블러 이후에 mask 수식어를 추가해줍니다.
.blur(radius: 8.0)
.mask(alignment: .center) { // <-- 여기서부터추가
RoundedRectangle(cornerRadius: 16.0)
.frame(height: 50)
.frame(maxWidth: geo.size.width - 16)
.blur(radius: 8.0)
}
여기까지 하셨으면, 다음과 같은 이미지 결과가 됩니다.
현재 ZStack이니 이 배경위에 올리기만하면 끝입니다.
이것은 버튼의 뒷배경을 담당할 예정입니다. 이제 배경위에 텍스트를 올려야겠죠?
Text("회원가입")
.font(.title2.bold())
.foregroundColor(.white)
이후에 원하시는 효과들을 섞어보세요. 저는 아래와 같이 했습니다.
Text("회원가입")
.blur(radius: 0.5)
.font(.title2.bold())
.foregroundColor(.white)
.frame(width: geo.size.width - 16)
.frame(height: 50)
.background(Color.black.opacity(0.3))
.overlay(
RoundedRectangle(cornerRadius: 16.0)
.stroke(.white, lineWidth: 1.9)
.blendMode(.normal)
.opacity(0.7)
)
.cornerRadius(16.0)
그리고 배경을 검정색으로 하고 실행시키면 다음과 같은 결과가 나타납니다.
아름다운 버튼이 완성되었습니다.^^ (프로젝트는 해당 README가 있는 디렉토리에 함께 추가해두겠습니다.)
https://github.com/kipsong133/TIL/tree/main/2022/02/24/SwiftUI%20GradientButton
읽어주셔서 감사합니다.