[Flutter] 그라데이션으로 만들어보는 광원 효과

LOCKED·2021년 12월 23일
117

Interaction

목록 보기
6/7
post-thumbnail

지난 포스트에서 3D 카드 인터렉션에 대해서 다룬적이 있었다.

삼성페이의 Card Interaction 구현

해당 글에서는 y축을 기준으로 회전하는 카드를 만들었는데, 오늘은 여기에 광원 효과를 추가해보려 한다.
광원효과라고 부르는게 맞는지는 모르겠으나, 대략 표면에 빛의 반사가 일어난 것 같이 보이는 효과를 말하고 싶었다.

..아무튼 이를 표현해보려고 한다.

광원 효과를 사용하는 앱에는 어떤 것들이 있을까.
먼저, 오늘 다뤄 볼 광원 효과를 활용하고 있는 앱을 살펴보자.


예시: 차이카드

차이카드에서 광원 효과를 다음과 같이 활용했다.

사실, 👀 팀 내 디자이너분께서 이런 효과는 어떻게 구현하냐고 여쭤보셔서 이 글을 작성하게 되었다.

카드의 움직임에 따라서 빛이 반사되는 위치가 변경되어 보인다.

차이카드에서는 왼쪽 방향 애니메이션, 오른쪽 방향 애니메이션이 각각 다른데, 이 두가지 중 왼쪽 방향 애니메이션에 대해서만 다뤄보도록 할 것이다.


빛의 반사

빛의 반사는 OpenGL을 해보았을 때 잠깐 다뤄보았다. OpenGL에선 조명을 설정할 수 있어 광원에 따라 오브젝트의 입체감이 달라진다.

그렇다면 플러터에서 비슷한 효과를 주기 위해서는 어떻게 해야할까?

첫 번째로 생각난 것은 gradient 이다.
RadialGradient를 사용하여 빛을 표현할 수 있지않을까?


Gradient

flutter에서 그라데이션 효과를 주기 위해서 gradient값을 설정해줘야한다.

Container(
  decoration: BoxDecoration(
    gradient: RadialGradient()
  ),
)

BoxDecoration 위젯 안에는 gradient라는 파라미터가 있고, 조명의 효과를 내기 위해서는 원형 그라데이션인 RadialGradient를 사용한다.

RadialGradient

다른 gradient와 마찬가지로 그라데이션 색상을 선언해야 한다.

RadialGradient(
  colors: gradientColors,
  stops: colorStops,
  center: radialCenter,
),

colors, stops의 값을 지정해줬는데, 이를 쉽게 설명하면 다음과 같다.

Keynote, PowerPoint, Photoshop등 그라데이션은 아래의 GUI로 구현되어있다.

이 이미지에서의 colors는 흰색과 보라색이 된다.
stops는 색상의 차지할 위치를 나타내며, 여기서는 0, 1이 된다.

RadialGradient(
  colors: [
    Colors.white,
    Colors.purple,
  ],
  stops: [0, 1],
),

stops의 개수는 colors의 개수와 같아야 한다.

RadialGradient 위젯에는 center라는 파라미터가 있는데 원형 그라데이션의 중심점의 위치를 말한다.
이를 활용하여 빛의 위치를 조절할 수 있다.


광원 효과 구현

구현 목표

위에서 예시 이미지를 목표로 구현을 시작해보려한다. 하지만 이 글의 목적은 광원효과이기 때문에 나머지 부분은 생략하며 글을 작성하겠다.

그럼 먼저 카드를 만들어보자.

카드 위젯

카드에는 그라데이션 효과를 부여해야하기 때문에 Container위젯을 사용하였다.

Container(
  decoration: BoxDecoration(
    gradient: RadialGradient(
      colors: [
        Colors.white,
        Colors.red,
      ],
      center: radialCenter,
    ),
  ),
  ...
)

간단하게 그라데이션을 적용해본 결과는 다음과 같다.

center의 기본 값은 Alignment(0, 0)으로 되어 있기 때문에 중앙이 흰색이고 끝쪽이 빨간색이다.

Alignment(0, 0) == Alignment.center
Alignment의 값 설정은 중앙이 (0, 0) 좌상단이 (-1, -1)이다.

예시 이미지에서는 좌상단에 중심점이 있기 때문에 중심점을 수정해보자.

    gradient: RadialGradient(
      ...
      center: Alignment(-1.6, 1),
    ),

좌상단 -> 우하단으로 내려오는 것처럼 보이게 하기 위해 적당한 값을 찾아보았다.

내 느낌대로 좌상단으로 광원의 위치를 조절하자, 그럴듯한 광원이 생긴듯 하다.
이제 지난 포스트를 참고하여 카드에 3D애니메이션을 적용한다.

삼성페이의 Card Interaction 구현
이 링크를 참고하면 어렵지 않게 가능할 것이라 예상한다.

광원 위치 조절

카드의 위치 광원의 위치를 조절하지 않고 3D 애니메이션을 적용한 결과는 다음과 같다.

카드를 누른다 라는 느낌을 주기 위해서 3D터치의 개념을 사용하였다. 카드 좌측을 눌렀기 때문에 누른 쪽이 뒤로 밀리는 것처럼 보이게 했다.

약간의 바운스도 추가하였다.
차이카드에서는 바운스 효과를 굉장히 남용한 편인데 여기에는 왜 적용 안했는지 모르겠다.

카드 애니메이션은 그럴듯 해보이지만, 광원이 없으니 평면이라는 느낌을 지울 수 없다.
테스트를 통해 광원의 위치(x좌표)를 -1.6 ~ 1.2 로 잡았다.

animation = Tween<double>(begin: -1.6, end:1.2).animate(animationController);

animation.valuecenter 에 적절하게 넣어주자.

예시 Alignment(-1.6, 1) ~> Alignment(1.2, -1)


광원 효과 결과

그라데이션을 이용해서 광원효과를 비슷하게나마 구현해보았다. 광원효과를 적용하니 입체적인 느낌이 든다. 한 화면에 카드밖에 없지만 저런 효과로 인해 앱의 완성도가 높아 보이는 듯하다.

좋은 생각이 있으시다면 피드백 주세요. 👀

좀 더 궁금하시다면, 댓글을 남겨주세요.

profile
Flutter 개발자 :'>

12개의 댓글

comment-user-thumbnail
2021년 12월 28일

오오 신기하네요!! 😀

1개의 답글
comment-user-thumbnail
2021년 12월 30일

그라데이션으로 빛을 표현하고 빛이 움직이니 3D 같아 보이는거군요?? 엄청 신박하네요 ㄷㄷ

1개의 답글
comment-user-thumbnail
2021년 12월 30일

흥미롭네요 잘 봤습니다

1개의 답글
comment-user-thumbnail
2021년 12월 31일

와 저도 플러터 개발하고 있어요! 애니메이션을 활용하니 훨씬 풍부한걸 표현할 수 있군요.
이전 포스팅도 구경했는데 저도 한번 배워봐야겠어요.ㅎㅎ 잘 보고 갑니다!!

1개의 답글
comment-user-thumbnail
2022년 5월 5일

멋짐 멋짐 ~ ★

답글 달기
comment-user-thumbnail
2022년 5월 21일

https://codepen.io/ywjung328/pen/JjpJaYW

Stack 으로 Radial Gradient 레이어를 적층하면 컨테이너의 자식 위젯도 동일한 효과를 볼 수 있습니다!! :D

전 다른거보다도 잡고 패닝하는거 처리하는게 어렵네요 ㅠㅠ 잡고 끌면 범위 안에선 움직이다가 놓으면 원래 위치로 복원되게 하고싶은데...

--수정-- 해결했습니다. setstate 떡칠인거보면 제대로 된 해결법은 아닌거같긴 한데..

답글 달기
comment-user-thumbnail
2023년 6월 3일

대단합니다.

답글 달기
comment-user-thumbnail
약 2시간 전

24년에도 여전히 유용하네요. 좋은 글 남겨주셔서 감사합니다.

답글 달기