[Flutter] CustomClipper와 ClipPath

향신료·2023년 11월 10일
0
post-thumbnail

CustomClipper<Path>를 기준으로 설명하는 글 입니다.




CustomClipper?


사용자가 커스텀 한 모양을 그리기 위한 클래스입니다, 예를 들면 쿠키틀과 같은 역할을 한다고 볼 수 있습니다.



기본적인 선언 형식으로 추상 클래스인 CustomClipper<T>를 상속받아 사용하며, T는 원하는 모양의 타입을 넣어주면 됩니다.

  • 일반적으로 클리핑 모양 타입은 Path를 사용합니다.
  • 필수적으로 shouldReclipgetClip 메서드를 재정의 해야만 합니다.

예시 코드

class CustomClipper extends CustomClipper<Path> {
  
  Path getClip(Size size) {
    final path = Path();
    // 원하는 경로 추가
    return path;
  }

	
  bool shouldReclip(CustomClipper<Path> oldClipper) {
    return false;
  }
}





shouldReclip

도양을 다시 그려야 하는지에 대한 여부를 반환하는 메서드입니다.


예를 들어 애니메이션 중에 클리핑 모양이 변경되어야 하는 경우 true를 반환하여 다시 모양을 그릴 수 있습니다.






getClip

getClip 메서드는 필수 재정의 메서드이며, 적용시킬 모양을 반환해야 합니다.


Size 매개변수를 통해 해당 크기 내에서 클리핑 모양을 그리며, Size 값은 상위 부모 위젯으로부터 받아 사용합니다.




몇 가지 Path 기초 메서드를 추가로 알아보도록 하겠습니다.


moveTo

현재 위치를 지정 좌표로 이동시키는 메서드입니다.


x, y의 순서로 좌표가 적용되며, 일반적으로는 해당 메서드를 이용하여 시작점을 설정합니다.

  • 이때 좌표를 이동시키기만 할 뿐 선을 잇는다거나 하는 액션은 진행되지 않습니다.

시작점을 0, 0 으로 사용하신다면 해당 메서드로 시작점을 설정하실 필요는 없습니다.

path.moveTo(50, 50); // 좌표를 (x, y)으로 이동







lineTo

현재 좌표에서 지정한 좌표까지 직선을 그리는 메서드입니다.

path.lineTo(150, 50); // 현 좌표에서 (x, y)까지 직선 그리기



해당 함수의 경우 단일로 사용되었을 경우 UI에서는 아무것도 보이지 않습니다.

  • 오직 단일 선 만으로 이루어져 면으로는 보이지 않음



예시 코드 및 구현 이미지


// 단일 lineTo 예제
class OneLineToClipper extends CustomClipper<Path> {
  
  Path getClip(Size size) {
    final path = Path();
    path.lineTo(150, 50);
    path.close();

    return path;
  }

  
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
    return false;
  }
}
// 2중 lineTo 예제
class TwoLineToClipper extends CustomClipper<Path> {
  
  Path getClip(Size size) {
    final path = Path();
    path.lineTo(150, 50);
    path.lineTo(0, 50);
    path.close();

    return path;
  }

  
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
    return false;
  }
}






quadraticBezierTo

현재 위치에서 제어점과 끝 점을 이용해 곡선을 그리는 메서드입니다.


path.quadraticBezierTo(100, 100, 150, 0); 
// 현 좌표에서 (x1, y1 x2, y2) 곡선 그리기

이때 x1, y1은 곡선의 형태와 방향을 제어하는 제어점의 x y 좌표이며, x2, y2는 끝 점의 좌표입니다.




예시 코드 및 구현 이미지

class QuadraticBezierToClipper extends CustomClipper<Path> {
  
  Path getClip(Size size) {
    final path = Path();
    path.quadraticBezierTo(100, 100, 150, 0);
    path.close();

    return path;
  }

  
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
    return false;
  }
}






close

현재 좌표에서 시작점을 연결하여 경로를 닫는 역할을 합니다.


필수 메서드는 아니지만 명시적 하기 위하여 작성해 주는 것이 좋습니다.


path.close();

더욱 다양한 Path 메소드는 공식 문서로 확인 가능합니다.

https://api.flutter.dev/flutter/dart-ui/Path-class.html






➕ Path의 그려지는 순서

Path는 별도로 정해진 순서 없이 사용자가 정의한 순서대로 선을 이어줍니다, 이는 예제를 통해 쉽게 알아볼 수 있습니다.


아래는 다이아몬드 다각형을 그리는 실제 코드와 빌드로 통해 나타는 결과입니다.

  • PolygonClipper 의 부모 위젯의 크기는 150*150의 위젯입니다.


class PolygonClipper extends CustomClipper<Path> {
  
  Path getClip(Size size) {
    final path = Path();
    path.moveTo(50, 0); // 시작점 세팅
    path.lineTo(100, 0);
    path.lineTo(150, 50);
    path.lineTo(75, 100);
    path.lineTo(0, 50);
    path.close();
    return path;
  }

  
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
    return false;
  }
}

해당 결과물 위에 선과 좌표, 순서를 참고용으로 적어둔 후 알아보면 아래 같으며 코드와 같이 시계 방향대로 그리고 있음을 알 수 있습니다.



그러면 점을 그리는 시작점과 반시계 방향으로 순서를 바꿔보겠습니다.


class PolygonClipper extends CustomClipper<Path> {
  
  Path getClip(Size size) {
    final path = Path();
    path.moveTo(75, 100); // 시작점 세팅
    path.lineTo(150, 50);
    path.lineTo(100, 0);
    path.lineTo(50, 0);
    path.lineTo(0, 50);
    path.close();
    return path;
  }

  
  bool shouldReclip(covariant CustomClipper<Path> oldClipper) {
    return false;
  }
}

업로드중..

시작점과 순서가 바뀌었음에도 그리는 도형의 형태는 여전함을 알 수 있습니다, 이처럼 해당 Path에서는 그리는 시작점과 그리는 방향의 중요성보다는 좌표값을 인지하고 원하는 위치에 지정하는 것이 휠씬 중요함을 알 수 있습니다.









ClipPath?


customCliper로 정의한 모양을 사용하여 하위 위젯의 모양을 클리핑 할 수 있는 위젯입니다.


클리핑 클래스로 만든 쿠키틀을 실제로 찍어낸 후의 결과를 보여주는 위젯이라고 볼 수 있습니다.

ClipPath(
  clipper: CustomClipper(), // 적용할 클리핑 클래스
  child: Container(   // 클리핑 적용되는 자식 위젯
				width: 250,
        height: 250,
        color: Colors.yellow,
  ),
)


공식 영상을 통해 이미지와 함께 간단한 설명을 확인할 수 있는 아래 영상도 존재하니 필요시 확인하면 좋을 듯합니다.

https://www.youtube.com/watch?v=oAUebVIb-7s







➕ 좀 더 편하게 사용할 수는 없나요?

다양한 CustomClipper를 제공해 주는 flutter_custom_clippers 패키지가 존재하니 해당 패키지에 필요한 Clipper가 존재한다면 해당 패키지를 사용하는 것 또한 개발 시간을 줄 일 수 있는 하나의 방법입니다.




flutter_custom_clippers 패키지 링크

https://pub.dev/packages/flutter_custom_clippers





해당 코드들의 전문은 Github 레파지토리에서 확인 가능합니다!

profile
드문드문 기초 정보를 올리는 블로그

0개의 댓글