Search code examples
flutterdartflutter-layout

How to Draw Shapes using Bezier Curves in a Flutter CustomPainter


I am trying to draw the picture below using the flutter customPainter library. How can I draw this shape?

enter image description here

My codes and the result

import 'package:flutter/material.dart';

class CurvePainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    var paint = new Paint();
    paint.color = Colors.green[800];
    paint.style = PaintingStyle.fill;

    var path = new Path();
    path.lineTo(0, size.height * 0.3);

    path.quadraticBezierTo(size.width * 0.35, size.height * 0.4, size.width * 0.7, size.height * 0.21);
    path.quadraticBezierTo(size.width * 0.6, size.height * 0.19, size.width * 0.9, size.height * 0.15);
    path.quadraticBezierTo(size.width , size.height * 0.05, size.width * 0.6, 0);

    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}

enter image description here


Solution

  • The Bézier curves you chose are not the correct ones.


    Here I illustrate where I applied which curves. The yellow dots are start & end points and the black dots represent control points.
    In the code, I went from left to right (top to bottom) and used arcToPoint instead of conicTo as it works better. Note that arcToPoint draws conic curves as well.

    Explanation illustration

    It is just a rough sketch, i.e. the proportions are completely off, but at least I can share the proper Bézier curves you should use in order to achieve your desired output.

    @override
    void paint(Canvas canvas, Size size) {
      final paint = Paint()
        ..color = Colors.red[800]
        ..style = PaintingStyle.fill;
    
      final path = new Path()
        ..moveTo(size.width * .6, 0)
        ..quadraticBezierTo(
        size.width * .7,
        size.height * .08,
        size.width * .9,
        size.height * .05,
      )
        ..arcToPoint(
        Offset(
          size.width * .93,
          size.height * .15,
        ),
        radius: Radius.circular(size.height * .05),
        largeArc: true,
      )
        ..cubicTo(
        size.width * .6,
        size.height * .15,
        size.width * .5,
        size.height * .46,
        0,
        size.height * .3,
      )
        ..lineTo(0, 0)
        ..close();
    
      canvas.drawPath(path, paint);
    }
    

    Note that I updated the syntax to use .. cascade notation and the final keyword for the variables.