Flutter. Understanding How to Draw Various Shapes Using the CustomClipper



Flutter offers various widgets for working with a specific set of shapes, for example ClipRect , ClipRRect , ClipOval . But there is also ClipPath , with which we can create any types of shapes.



In this article, we'll focus on what you can do using ClipPath and CustomClipper . Go!



Content:





ClipPath



Thanks to ClipPath, we can create very complex and unusual shapes. The clipper property of ClipPath will help us with this.



@override
Widget build(BuildContext context) {
  return Scaffold(
    backgroundColor: Colors.grey,
    body: Center(
      child: ClipPath(
        clipper: MyCustomClipper(), // <--
        child: Container(
          width: 200,
          height: 200,
          color: Colors.pink,
        ),
      ),
    ),
  );
}


The value for clipper must be an instance of the class that the CustomClipper<Path>two methods inherit and override.



class MyCustomClipper extends CustomClipper<Path> {
  @override
  Path getClip(Size size) {
    Path path = Path();
    return path;
  }

  @override
  bool shouldReclip(CustomClipper<Path> oldClipper) => false
}


getClip , . Size, , hild ClipPath.



shouldReclip , clipper . , true, – false.



CustomClipper. , .





, (x,y). x , y – . , (0, 0).



. .



lineTo



.





(a), p1(0, 0). p2(0, h), – p3(w, h). p3 p1, .



(b) .



@override
Path getClip(Size size) {

  Path path = Path()
    ..lineTo(0, size.height) //   p1p2
    ..lineTo(size.width, size.height) //   p2p3
    ..close();

  return path;
}


moveTo



.





, (0, 0) p1(w/2, 0).



@override
Path getClip(Size size) {

  Path path = Path() //    (0, 0)
    ..moveTo(size.width/2, 0) //    (width/2, 0)
    ..lineTo(0, size.width)
    ..lineTo(size.width, size.height)
    ..close();

  return path;
}


quadraticBezierTo



.





: Wikipedia



, , . P0 – , P1 –  , P2 – .





(), p2(0, h) p3(w, h) c(w/2, h/2).



@override
Path getClip(Size size) {
  //      ,      quadraticBezierTo
  var controlPoint = Offset(size.width / 2, size.height / 2);
  var endPoint = Offset(size.width, size.height);

  Path path = Path()
    ..moveTo(size.width / 2, 0)
    ..lineTo(0, size.height)
    ..quadraticBezierTo(
        controlPoint.dx, controlPoint.dy, endPoint.dx, endPoint.dy)
    ..close();

  return path;
}


cubicTo



2 .





.





(a), p2 p3 c1 c2.



@override
Path getClip(Size size) {

  var controlPoint1 = Offset(50, size.height - 100);
  var controlPoint2 = Offset(size.width - 50, size.height);
  var endPoint = Offset(size.width, size.height - 50);

  Path path = Path()
    ..moveTo(size.width / 2, 0)
    ..lineTo(0, size.height - 50)
    ..cubicTo(controlPoint1.dx, controlPoint1.dy, controlPoint2.dx,
        controlPoint2.dy, endPoint.dx, endPoint.dy)
    ..close();

  return path;
}


arcToPoint



. , , ( / ).





. , (x, y), – R.





(a) , p1. p2 p3, , , , . p4 p5 (. – ). p6 p7, . p8 p1, .



@override
Path getClip(Size size) {

  double radius = 20;

  Path path = Path()  
    ..moveTo(radius, 0)
    ..lineTo(size.width-radius, 0)
    ..arcToPoint(Offset(size.width, radius))
    ..lineTo(size.width, size.height - radius)
    ..arcToPoint(Offset(size.width - radius, size.height),radius: Radius.circular(radius))
    ..lineTo(radius, size.height)
    ..arcToPoint(Offset(0, size.height - radius), radius: Radius.circular(radius), clockwise: false)
    ..lineTo(0, radius)
    ..arcToPoint(Offset(radius, 0), radius: Radius.elliptical(40, 20))
    ..close();

  return path;
}


arcTo



, , Rect, (startAngle) (sweepAngle).





. 0 PI ( PI ~3.14), – 2 PI.





Rect, , , LTRB (Left, Top, Right, Bottom) LTWH (Left, Top, Width, Height). (a) .



@override
Path getClip(Size size) {

  double radius = 50;

  Path path = Path()
    ..lineTo(size.width - radius, 0)
    ..arcTo(
        Rect.fromPoints(
            Offset(size.width - radius, 0), Offset(size.width, radius)), // Rect
        1.5 * pi,   //  
        0.5 * pi,  //  
        true)  //    
    ..lineTo(size.width, size.height - radius)
    ..arcTo(Rect.fromCircle(center: Offset(size.width - radius, size.height - radius), radius: radius), 0, 0.5 * pi, false)
    ..lineTo(radius, size.height)
    ..arcTo(Rect.fromLTRB(0, size.height - radius, radius, size.height), 0.5 * pi, 0.5 * pi, false)
    ..lineTo(0, radius)
    ..arcTo(Rect.fromLTWH(0, 0, 70, 100), 1 * pi, 0.5 * pi, false)
    ..close();

  return path;
}


addRect



. Rect: fromPoints, fromLTWH, fromCircle, fromLTRB fromCircle.






@override
Path getClip(Size size) {

  Path path = Path()
    ..addRect(Rect.fromPoints(Offset(0, 0), Offset(60, 60)))
    ..addRect(Rect.fromLTWH(0, size.height - 50, 50, 50))
    ..addRect(Rect.fromCircle(center: Offset(size.width / 2, size.height / 2), radius: 20))
    ..close();

  return path;
}


addRRect



. , , .





@override
Path getClip(Size size) {
    double radius = 10;

    Path path = Path()
      ..addRRect(RRect.fromLTRBR(0, 0, 60, 60, Radius.circular(radius)))
      ..addRRect(RRect.fromRectAndRadius(
          Rect.fromLTWH(0, size.height - 50, 50, 50), Radius.circular(radius)))
      ..addRRect(RRect.fromRectAndCorners(
          Rect.fromCircle(
              center: Offset(size.width / 2, size.height / 2), radius: 30
          ),
          topLeft: Radius.circular(radius)))
      ..close();

    return path;
}


addOval



. addRect, Rect .





@override
Path getClip(Size size) {

    Path path = Path()
      ..addOval(Rect.fromPoints(Offset(0, 0), Offset(60, 60)))
      ..addOval(Rect.fromLTWH(0, size.height - 50, 100, 50))
      ..addOval(Rect.fromCircle(center: Offset(size.width / 2, size.height / 2), radius: 20))
      ..close();
    return path;

}


addPolygon



.





@override
Path getClip(Size size) {
    var points = [
      Offset(size.width / 2, 0), //  p1
      Offset(0, size.height / 2), //  p2
      Offset(size.width / 2, size.height), //  p3
      Offset(size.width, size.height / 2) //  p4
    ]; 

    Path path = Path()
      ..addPolygon(points, false)
      ..close();

    return path;
}


addPath



, . .





(a), (path 1 path 2), path 1 , path 2 path 1. path 2 (w/2, 0), (0, 0) .



@override
Path getClip(Size size) {

    Path path1 = Path()
      ..lineTo(0, size.height)
      ..lineTo(size.width/2, size.height)
      ..lineTo(0, 0);

    Path path2 = Path()
      ..lineTo(size.width/2, size.height)
      ..lineTo(size.width/2, 0)
      ..lineTo(0, 0);

    path1.addPath(path2, Offset(size.width/2,0));

    return path1;
}


relativeLineTo



lineTo, , .





(a) p1p2 relativeLineTo, p2 p1. p2(x, y) = (p1.x + 50, p1.y + h)



@override
Path getClip(Size size) {

    Path path = Path()
      ..moveTo(size.width/2, 0)
      ..relativeLineTo(50, size.height)
      ..lineTo(size.width , size.height)
      ..close();

    return path;
}


: relativeMoveTo, relativeQuadraticBezierTo, relativeArcToPoint, relativeCubicTo quadraticBezierTo, arcToPoint, cubicTo , relativeLineTo lineTo.





I hope this material will be useful to you and help you create new cool shapes.









All Articles