[Flutter] 밀리의 서재 뷰어

locked·2021년 12월 20일
11
post-thumbnail

이번 포스트에서는 앱 <밀리의 서재>의 기능 중 일부를 구현해보려한다.

우연히 <밀리의 서재> 웹 사이트에서 앱을 소개하는 동영상을 보았는데 흥미로운 부분이 있었다.
바로 시선 감지(Eye Tracking)뷰어 내부의 스타일 변경 인터랙션, UX이다.

재밌어 보이는 기능, 인터랙션 이였기 때문에 두가지 기능 모두 구현해보려 했었는데, 시선 감지의 정확도가 좀 떨어져서 뷰어 내부의 스타일 변경 인터랙션만 작성하려 한다.

밀리의 서재에서는 drawer에서 텍스트 스타일을 커스텀할 수 있는데, 이 과정에서의 UX를 굉장히 잘 만들었다고 생각한다.

그래서, 어떤 UX인데??

밀리의서재 - 자유로운 보기 설정

위의 이미지에서 볼 수 있듯이, 폰트 사이즈를 변경하게되면, 뒤의 글의 크기가 실시간으로 변경되며 이를 바로 확인할 수 있다.

이 과정에서 유저가 드래그하고 있는 영역을 제외하고는 투명하게 변한다.
텍스트 크기를 표현하는 숫자가 얼마나 크고 작은지, 바로 눈으로 확인하여 쉽게 알 수 있게 하였다.

드로워(Drawer)?

햄버거 버튼으로도 불리는 메뉴 버튼을 누르면 나오는 옆에서 튀어나오는 화면을 본적이 있을 것이다.
이것을 Drawer라고 한다. Drawer는 나오는 방향에 따라 이름을 다르게 부르는데 왼쪽 -> 오른쪽이면 Drawer, 오른쪽 -> 왼쪽이면 EndDrawer라고 부른다.

이는 Scaffold에서 선언할 수 있다.

Scaffold(
  drawer: const MyDrawer(),
  endDrawer: const MyEndDrawer(),
);

밀리의 서재에서는 오른쪽 -> 왼쪽으로 나오는 Drawer를 사용했으니, endDrawer를 사용하여 구현하면 된다.

Scaffold Drawer

뒷 배경 색상 제거

기본적으로 drawer를 생성하게 되면, 화면에 overlay가 된 것이기 때문에 뒷 배경 색상이 존재한다. 뒷 배경을 잘 보기 위해서는 이를 제거해야하고, 제거하기 위해서는 색상을 지정해주면 된다.

Scaffold(
  drawerScrimColor: Colors.transparent,
  ...
)

Drawer 선언

색상을 제거하고 endDrawer에Drawer() 를 선언해준다.

Drawer(
  child: ...
),

투명한 Drawer

drawer의 생성을 하였는데, <밀리의 서재>의 예시처럼 하기 위해서는 일부 영역을 제외한 나머지 부분들이 투명해져야 한다.

Drawer의 뒷 배경부터 투명하게 해보자. Drawer의 뒷 배경 색상은 Theme의 canvasColor를 따라간다. 해당 색상을 투명한 색으로 지정해주면 drawer가 투명해지는 것을 볼 수 있다.

MyTheme(
  canvasColor: Colors.transparent,
  ...
),

투명한 내부 위젯

drawer의 배경을 투명하게 만드는 것은 색상을 변경했는데, drawer내부의 위젯들이 그대로 남아있다. 특정 조건을 만족하면 이들도 같이 투명하게 바꿔준다.

void onChangeVisibilty(){
  visible.toggle();
  if(visible){
    canvasColor = Colors.black;
    ...
  }else{
    canvasColor = Colors.transparent;
    ...
  }
}

Draggable Widget

위에서 어느 시점일지는 모르지만, 포커스된 위젯을 제외하고 투명해지는 함수를 만들었다.
이제 드로워 내부의 드래그 가능한 위젯을 만들어보자. 함수를 호출하는 시점은 해당 위젯을 드래그하였을 때로 정한다.

GestureDetector에 있는 onHorizontalDragUpdate를 사용하여 드래그 가능한 위젯을 만드려고한다. golbalPosition을 이용하면 현재 터치 이벤트가 발생한 위치를 알 수 있고, 이를 이용해 글자 크기를 변경하면 된다.

GestureDetector(
  onHorizontalDragUpdate: (DragUpdateDetails dragUpdateDetails){
    pointer = _.globalPosition.dx
    ...
  }
),

AnimatedContainer 위젯을 사용한다면 좀 더 부드러운 변화를 줄 수 있다.

AnimatedContainer(
  duration: duration,
  width: widthFromPosition,
  ...
),

드래그할 때, 위젯 크기가 변하는건.. Transform.scale

나머지 위젯

drawer의 배경색은 투명해지겠지만, 아직 나머지 위젯들이 투명해지지 않았다.
이를 투명하게 하기 위해서 나머지 위젯들을 AniamtedOpacity위젯으로 감싸면된다.

결과

아이유의 라일락 가사

확실히 사용성이 좋은 UX, 인터랙션인 것 같으며 활용할 영역이 좀 더 있을 것 같다.
밀리의 서재의 시선감지 기능도 정확도를 높이는 방법을 찾게 된다면 글을 써보겠다..

profile
Flutter 개발자

0개의 댓글