SVG to Flutter path

SVG to Flutter path
This article has been updated! Tap to see
  • April 10, 2022: Made code open source, uploaded it to GitHub
Tip
If you just want to see how it works and skip the step of creating an SVG just head over to the converter and hit the example button. Same applies if you already have an SVG.

Especially when using bezier curves, it quickly becomes cumbersome to work with a Path object in Flutter and iteratively adapt the values. In this tutorial, we will find a way to quickly produce beautiful and complex paths with no code editing.

The issue

The challenge is: we are dealing with a visual problem but we are trying to solve it in the code. Having no preview while editing values in our bezier curves makes it a very fiddly task.

The goal

Let’s learn an approach that fulfills the following requirements:

  • The initial creation is very easy because there is visual output
  • Everything can be done very quickly within a matter of seconds or minutes
  • Afterwards adjustments are easily possible

The example

Flutter bezier curves example
This is the example we will be working on

To show a practical usage of the tutorial we will follow an example in which we produce two decorative paths, one at the top and one at the bottom to make our screen more appealing.

Visual creation

Let’s start by creating our SVG file. In this tutorial I will use Inkscape, which is an open source vector graphics editor. You’re free to use anything else that fits the purpose, e. g. Adobe Illustrator or Sketch. The procedure is very similar.

Inkscape bezier tool
Inkscape bezier tool

From the toolbox of your vector software choose the bezier tool. We use this tool because we want to have custom shapes with curves.

The bezier tool allows us to set the points of our path. When holding the left mouse button, we can intuitively choose the degree of the curve (implicity setting control points of the bezier curve).

Inkscape bezier curve
It does not have to be perfect right away

Now we try to create the red shape, starting on the upper left. It is important to know that it does not have to be perfect right away. We can adjust everything later. Trying to make it perfect just wastes time. So we make a rough estimation of our shape.
After that we do the same for our orange shape. It does not really matter where we place it. What is important, though: the distance from the path to the (imaginary) left border. This distance (relative to the width of our shape) will be the actual used distance in the flutter Path later on. So if you want the path to end at 50 % horizontally in your screen later, you should let it end there in Inkscape as well.
We also take care that both of our paths are closed, meaning that we set the last point of our path by clicking on the initial point.

Making adjustments

Now that we have rough estimations of our shapes, we make adjustments by using the node tool. This allows us to reposition points of our bezier paths. If we want to automatically smoothen the paths, we can use Path > Simplify or CRTL + L on Windows or CMD + L on the Mac.
Also, we give the shapes the color we want to have by selecting the shape and clicking on the fill on the bottom left.

Inkscape node tool
Afterwards adjustments are easily possible

An important note: the converter takes every path within the SVG file and takes the boundaries of the collection as the boundaries for creating the Flutter path. That means: if we wanted e. g. a padding of the red path to the left border of our canvas which resulted in a padding in our app screen later on, we would need to add a rectangle around everything, starting at (0,0) and move the red path further right.

Using the converter

Before we save the file, we make sure that everything is positioned at (0,0) of the canvas. Then we head over to the converter.
We click the Upload SVG button and choose the file from our harddisk we have just created.

SVG converter Flutter code output
The code output of the converter

The converter gives us a code output that we can just copy off.

Insert the code into Flutter

We create a new widget and put the paths we got from the converter in two different CustomPainter widgets. If we had created two separate SVG files for every path, we would have gotten the correct output right away. But the creation in Inkscape would have taken a little longer. That’s why we went for the single-SVG-file-approach.

 1import 'package:flutter/material.dart';
 2
 3class Test extends StatelessWidget {
 4  @override
 5  Widget build(BuildContext context) {
 6    return Stack(
 7      children: <Widget>[
 8        Align(
 9            alignment: Alignment.topLeft,
10            child: CustomPaint(
11                painter: HeaderPainter(),
12                child: SizedBox(
13                    width: MediaQuery.of(context).size.width,
14                    height: 300
15                )
16            )
17        ),
18        Align(
19            alignment: Alignment.bottomLeft,
20            child: CustomPaint(
21                painter: FooterPainter(),
22                child: SizedBox(
23                    width: MediaQuery.of(context).size.width,
24                    height: 300
25                )
26            )
27        ),
28      ],
29    );
30  }
31
32}
33
34class HeaderPainter extends CustomPainter {
35  @override
36  void paint(Canvas canvas, Size size) {
37    Paint paint = Paint();
38    Path path = Path();
39
40    // Path number 1
41
42    paint.color = Color(0xFFFF5252);
43    path = Path();
44    path.lineTo(0, size.height);
45    path.cubicTo(size.width * 0.09, size.height * 0.93, size.width * 0.11, size.height * 0.78,size.width * 0.11, size.height * 0.66);
46    path.cubicTo(size.width * 0.11, size.height * 0.49, size.width * 0.16, size.height * 0.37,size.width / 4, size.height * 0.28);
47    path.cubicTo(size.width * 0.36, size.height * 0.23, size.width * 0.54, size.height * 0.18,size.width * 0.68, size.height * 0.16);
48    path.cubicTo(size.width * 0.81, size.height * 0.13, size.width * 0.89, size.height * 0.07,size.width * 0.98, 0);
49    path.cubicTo(size.width * 0.94, 0, size.width * 0.86, 0,size.width * 0.84, 0);
50    path.cubicTo(size.width * 0.56, 0, size.width * 0.28, 0,0, 0);
51    path.cubicTo(0, 0, 0, size.height,0, size.height);
52    canvas.drawPath(path, paint);
53  }
54  @override
55  bool shouldRepaint(CustomPainter oldDelegate) {
56    return true;
57  }
58}
59
60class FooterPainter extends CustomPainter {
61  @override
62  void paint(Canvas canvas, Size size) {
63    Paint paint = Paint();
64    Path path = Path();
65
66    paint.color = Color(0xFFFFAB40).withOpacity(1);
67    path = Path();
68    path.lineTo(size.width, size.height / 5);
69    path.cubicTo(size.width, size.height / 5, size.width * 0.94, size.height * 0.88,size.width * 0.65, size.height * 0.93);
70    path.cubicTo(size.width * 0.36, size.height * 0.97, size.width / 5, size.height,size.width / 5, size.height);
71    path.cubicTo(size.width / 5, size.height, size.width, size.height,size.width, size.height);
72    path.cubicTo(size.width, size.height, size.width, size.height / 5,size.width, size.height / 5);
73    canvas.drawPath(path, paint);
74  }
75  @override
76  bool shouldRepaint(CustomPainter oldDelegate) {
77    return true;
78  }
79}

We insert the paths into the widget tree by using a CustomPaint to let it draw and an Align widget to position it at the top and the bottom.

Flutter bezier curves example empty
Empty screen with our paths
Flutter bezier curves example
The screen brought to life

Final thoughts

With an idea in mind and a program that is able to create SVG files, we can easily let our imagination become (virtual) reality within just a minute. By uploading the SVG file into the SVG to Flutter path converter we get the Dart code directly which we can insert in our code and instantly see the result. A comfortable alternative to creating curves manually in the code.

Comments (13) ✍️

Mark Jose Ultra

I doesn’t work, I created an SVG using AI
Reply to Mark Jose Ultra

Marc
In reply to Mark Jose Ultra's comment

Oh, I’m sorry. Will you send me an e-mail with the respective SVG file and I tell you what might be the problem? It’s flutterclutterdev (at) gmail (dot) com
Reply to Marc

Isaac
In reply to Mark Jose Ultra's comment

Hi! Had the same issue, then I noticed the opacity was set to 0 on the path after the given color. Hope it’s useful!
Reply to Isaac

Isaac
In reply to Isaac's comment

Forgot to say I changed it from 0 to 1 like this: paint.color = Color(0xffffffff).withOpacity(1); Good luck and Marc, thanks for making this AMAZING tool, I love it!
Reply to Isaac

Omar Ahmed

I get a black screen using the above code .
Reply to Omar Ahmed

Marc
In reply to Omar Ahmed's comment

Hey Omar,

would you share the output code with me (e. g. via https://codeshare.io) so I can have a look at it? You might as well share the SVG if you want.

Thank you!

Reply to Marc

J.C.Ködel

It doesn’t work for optimized SVGs. Please, see codeshare.io 5zLvg4 It has a SVG and the generated code.
Reply to J.C.Ködel

Marc
In reply to J.C.Ködel's comment

Please try to remove all groups and try again. If it still does not work, let me know and I will have a look at it :).
Reply to Marc

Fahad Ammar

Could you please tell me how does the SVG XML to flutter code conversion takes place? Send me the e-mail
Reply to Fahad Ammar

Marc
In reply to Fahad Ammar's comment

You’ve got mail :)
Reply to Marc

Vayu

Marc, what you have made is absolute gold. Anyone can do wonders combining it with shadows and rewriting it into a simple CustomClipper class. I wish I could buy you a hundred coffees, or maybe someday, when my app’s out. Great work :)
Reply to Vayu

Marc
In reply to Vayu's comment

Thank you for your appreciation :). Glad I could help.
Reply to Marc

Youcef EL KAMEL

Hello,

I prefer the old version of your converter.

Now every svg that I took from thenounproject is not working.

I think it’s because of that: “sure that everything is positioned at (0,0) of the canvas.”

The problem is I don’t know how to do that and also it was working really nice before…

Awesome project by the way.

Regards, Youcef

Reply to Youcef EL KAMEL

Comment this 🤌

You are replying to 's commentRemove reference