[Flutter] 다음웹툰 Interaction 따라하기...(1)

LOCKED·2021년 5월 5일
13

CustomPainter

목록 보기
3/3

이번 포스트는 다음웹툰의 Interaction을 따라 구현해보고자 한다.
Interaction 때문인지 개인적인 의견으로는 사용하는 앱중에 단연 최고의 경험을 준다고 생각한다(서비스제외).

이번에 따라구현해 볼 것은 첫 다음웹툰의 메인화면 애니메이션이다.

처음부터 다음웹툰의 Interaction을 다 구현한다기 보다 순차적으로 나눠 구현을 진행하려 한다.

기본 도형 변경 - 사각형

첫 번째로 구현해 볼 것은 기본 도형 변경이다.
다음웹툰의 메인화면에서도 알 수 있듯이, 결국 화면에 보이는 좌표의 이동을 통해서 자연스러운 도형의 변경을 만들어낸 것이다.

기초 도형인 사각형으로 회전을 구현해본다.

사각형 만들기

사각형은 4개의 점으로 이루어진 도형이다. 이를 Path로 구현해본다.

// Begin
path.moveTo(0, 0);
// Top
path.lineTo(0, 0);
path.lineTo(size.width, 0);
// Bottom
path.lineTo(size.width, size.height);
path.lineTo(0, size.height);
// End
path.close();

결과

CustomPaint의 사이즈에 따라서 사각형이 그려지게 된다.

회전하는 사각형

위에서 그린 사각형을 회전시키기 위해서는 여러가지 방법이 있겠지만, 이번 포스트에서는 두가지 방법으로 구현해보려한다.

Rotate

첫 번째 방법은 canvas를 회전시키는 방법이다.

canvas.rotate(pi / 180 * 45);
canvas.drawPath(path, paint);

canvas에 Path를 그리기 전에 canvas를 회전시키면 된다.
하지만 이렇게 되면 canvas는 (0,0)을 기준으로 회전을 하게되므로 아래와 같은 형태가 된다.

Open GL 내용과 같다.

  • 기준점좌 상단을 기준으로 회전을 하기 때문

도형만 회전하고 싶다면, canvas를 도형의 중간으로 옮긴 후 회전을 하면 된다.

canvas.translate(xCenter, yCenter);
canvas.rotate(pi / 180 * v * 45);
canvas.translate(-xCenter, -yCenter);

Point Animation

두 번째 방법은 좌표 자체를 움직이는 방법이다.
회전과 같이 간단한 동작은 rotate를 하면 되겠지만, 각 좌표별 다른 움직임을 원할 때는 이 방법을 사용하면 될 것 같다.

직선 이동

사각형을 회전하였을 때, 사각형에 내접하는 마름모로 변하기 위해서는 직선 이동을 해야한다.

path.moveTo(0 + (size.width / 2 * value), 0);
// Top
path.lineTo(0 + (size.width / 2 * value), 0);
path.lineTo(size.width, 0 + (size.height / 2 * value));
// Bottom
path.lineTo(size.width - (size.width / 2 * value), size.height);
path.lineTo(-gap, size.height - (size.height / 2 * value));
// End
path.close();
  • value는 0~2 를 반복하는 숫자

Sin 이동

Rotate했을 때와 결과를 같게 하기 위해서는 직선의 길이가 같아야 하며, 삼각함수를 이용하여 좌표를 계산해야 한다.

var gap =
    (sqrt(2) * size.width / 2 - size.width / 2) * sin(pi / 2 * value);

이 때, gap 변수를 각 Path의 lineTo에 적절히 적용한다. 해당 코드는 정사각형 기준이다.

  • 대신 마름모 꼴로 변했을 때, Layout 영역을 침범할 수 있다.

PageView 적용

다음웹툰과 같이 적용하기 위해 PageView와 연동하여 사용한다.

  • PageController 를 value로 사용

profile
Flutter 개발자 :'>

0개의 댓글