How to fill color inside a shape created using CustomPainter drawPath? - flutter

So, I've created a shape using drawPath and drawArc from CustomPainter, the PaintingStyle is stroke, but when I change it to fill, it only fills the arcs and not the whole shape.
I want to fill the shape I created with a color, so how can I fill the shape with a particular color?
class CustomShapeCard extends CustomPainter {
CustomShapeCard({#required this.strokeWidth, #required this.color});
final double strokeWidth;
final Color color;
#override
void paint(Canvas canvas, Size size) {
var paint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = strokeWidth
..color = color;
var path = Path();
path.moveTo(size.width * 0.1, size.height * 0.2);
path.lineTo(size.width * 0.1, size.height * 0.9);
canvas.drawPath(path, paint);
canvas.drawArc(
Rect.fromCenter(
center: Offset((size.width * 0.2) - 14, size.height * 0.9),
height: 50,
width: 50,
),
math.pi / 2,
math.pi / 2,
false,
paint,
);
path.moveTo((size.width * 0.2) - 14, (size.height * 0.9) + 25);
path.lineTo((size.width * 0.9) - 25, size.height * 0.9 + 25);
canvas.drawPath(path, paint);
canvas.drawArc(
Rect.fromCenter(
center: Offset((size.width * 0.9) - 25, size.height * 0.9),
height: 50,
width: 50,
),
math.pi / 2,
-math.pi / 2,
false,
paint,
);
path.moveTo((size.width * 0.9), (size.height * 0.9));
path.lineTo(size.width * 0.9, size.height * 0.35);
canvas.drawPath(path, paint);
canvas.drawArc(
Rect.fromCenter(
center: Offset((size.width * 0.9) - 25, size.height * 0.35),
height: 50,
width: 50,
),
-math.pi / 2,
math.pi / 2,
false,
paint,
);
path.moveTo((size.width * 0.9) - 25, (size.height * 0.35) - 25);
path.lineTo(size.width * 0.25, (size.height * 0.35) - 25);
canvas.drawPath(path, paint);
canvas.drawArc(
Rect.fromCenter(
center: Offset((size.width * 0.25), (size.height * 0.35) - 50),
height: 50,
width: 50,
),
math.pi / 2,
math.pi / 3,
false,
paint,
);
path.moveTo((size.width * 0.25) - 20, (size.height * 0.35) - 35);
path.lineTo(size.width * 0.1, size.height * 0.2);
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}
When the PaintingStyle is stroke, I get this,
When I change PaintingStyle to fill, I get,

To fill a shape like this with a color,
the arcToPoint() should be used instead of drawArc().

Related

How to fill a line depending on a percentage using Canvas in Flutter?

I have a map that displays markers with data. On the right side of the marker there is an indicator in the form of a purple stripe. I need to make this indicator dynamic so that I can set a value in % and, depending on this value, the bar is filled with red. If the value is 100% then a completely red stripe, if 60% then a little more than half of the red color and the rest is green. I was drawing a strip using Canvas, but now I'm facing the problem that I don't know how can I make this strip dynamic, two-colored and dependent on %? I will be grateful for help
class PointPainter extends CustomPainter {
PointPainter({this.isClosed = false});
final bool isClosed;
#override
void paint(Canvas canvas, Size size) {
final strokeWidthThin = size.width * 0.07;
Paint paintMain = Paint()
..style = PaintingStyle.stroke
..strokeWidth = strokeWidthThin
..color = constants.Colors.purpleMain;
Paint paintPurpleThin = Paint()
..style = PaintingStyle.stroke
..strokeWidth = strokeWidthThin
..color = constants.Colors.purpleMain;
Paint paintPurpleBold = Paint()
..style = PaintingStyle.stroke
..strokeWidth = size.width * 0.16
..color = constants.Colors.purpleMain;
Paint paintGreen = Paint()
..style = PaintingStyle.stroke
..strokeWidth = strokeWidthThin
..color = constants.Colors.purpleMainDark.withOpacity(isClosed ? 0.5 : 1);
Paint paintTransparent = Paint()
..style = PaintingStyle.stroke
..strokeWidth = size.width * 0.04
..color = constants.Colors.purpleMainDark;
final pathMain = Path()
..moveTo(size.width / 2, size.height * 1.05)
..lineTo(size.width / 2 - size.width * 0.3, size.height * 0.4)
..arcToPoint(
Offset(size.width - size.width * 0.2, size.height * 0.3),
clockwise: true,
radius: const Radius.circular(0.9),
)
..lineTo(size.width / 2 + size.width * 0.3, size.height * 0.4);
final pathGreen = Path()
..moveTo(size.width / 2 + size.width * 0.3, size.height * 0.4)
..lineTo(size.width / 2, size.height)
..arcToPoint(
Offset(size.width - size.width * 0.22, size.height * 0.26),
clockwise: true,
radius: const Radius.circular(0.9),
);
final pathPurpleThin = Path()
..moveTo(size.width / 2, size.height * 1.05)
..lineTo(size.width / 2 - size.width * 0.3, size.height * 0.4);
final pathPurpleBold = Path()
..moveTo(size.width * 0.54, size.height * 1.03)
..lineTo(size.width / 2 + size.width * 0.3, size.height * 0.45);
final pathTransparent = Path()
..moveTo(size.width * 0.44, size.height)
..lineTo(size.width * 0.58, size.height * 0.68);
pathMain.close();
pathGreen.close();
pathPurpleThin.close();
pathTransparent.close();
if (!isClosed) {
canvas.drawPath(pathMain, paintMain);
canvas.drawPath(pathGreen, paintGreen);
canvas.drawPath(pathPurpleThin, paintPurpleThin);
canvas.drawPath(pathTransparent, paintTransparent);
}
canvas.drawPath(pathPurpleBold, paintPurpleBold);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
body
ClipPath(
clipper: PointClipper(),
child: Container(
width: width,
height: height,
color: constants.Colors.purpleMainDark,
child: CustomPaint(
painter: PointPainter(isClosed: isClosed),
),
),
),
point_clipper
class PointClipper extends CustomClipper<Path> {
PointClipper();
#override
Path getClip(Size size) {
//top
final path0 = Path();
path0..moveTo(size.width / 2, size.height * 0.4)
..lineTo(size.width / 2 - size.width * 0.3, size.height * 0.4)
..arcToPoint(
Offset(size.width - size.width * 0.2, size.height * 0.3),
clockwise: true,
radius: const Radius.circular(0.9),
)
..lineTo(size.width / 2 + size.width * 0.3, size.height * 0.4);
path0.close();
//bottom
path0.moveTo(size.width * 0.43, size.height * 0.9);
path0.quadraticBezierTo(size.width * 0.5, size.height * 1.1,
size.width * 0.57, size.height * 0.9);
path0.quadraticBezierTo(size.width * 0.6, size.height * 0.9,
size.width * 0.43, size.height * 0.9);
path0.close();
//middle
path0..moveTo(size.width * 0.43, size.height * 0.9)
..lineTo(size.width * 0.57, size.height * 0.9)
..lineTo(size.width / 2 + size.width * 0.3, size.height * 0.4)
..lineTo(size.width / 2 - size.width * 0.3, size.height * 0.4);
path0.close();
return path0;
}
#override
bool shouldReclip(PointClipper oldClipper) => true;
}

How to create an inner shadow for custom shape in Flutter?

Below is the custom shape I've want to give an inner shadow to :
Below is the code I've used to create this shape : (The text part is not included in the code)
class TitleContainerPaint extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
// TODO: implement paint
Paint x = Paint()..color = Colors.grey ..style = PaintingStyle.fill;
Path a = Path();
a.moveTo(size.height * 0.5, 0);
a.lineTo(size.width * 0.3, 0);
a.cubicTo(size.width * 0.325, 0, size.width * 0.325, size.height * 0.5 - 10, size.width * 0.35, size.height * 0.5 - 10);
a.lineTo(size.width * 0.825, size.height * 0.35);
a.cubicTo(size.width * 0.85, size.height * 0.5 - 10, size.width * 0.85, size.height * 0.15, size.width * 0.875, size.height * 0.15);
a.lineTo(size.width - size.height * 0.25, size.height * 0.15);
a.arcTo(Rect.fromCircle(center: Offset(size.width - size.height * 0.35,size.height * 0.5), radius: size.height * 0.35), -pi/2, pi, false);
a.lineTo(size.width * 0.875, size.height * 0.85);
a.cubicTo(size.width * 0.85, size.height * 0.85, size.width * 0.85, size.height * 0.5 + 10, size.width * 0.825, size.height * 0.5 + 10);
a.lineTo(size.width * 0.35, size.height * 0.65);
a.cubicTo(size.width * 0.325, size.height * 0.5 + 10, size.width * 0.325, size.height, size.width * 0.3, size.height);
a.lineTo(size.height * 0.5, size.height);
a.arcTo(Rect.fromCircle(center: Offset(size.height * 0.5,size.height * 0.5), radius: size.height * 0.5), pi/2, pi, false);
canvas.drawPath(a, x);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
// TODO: implement shouldRepaint
return true;
}
}
As mentioned in the question, my goal is to add an inner shadow to this shape like the image below :
Can someone please help me achieve this?
Thankyou in advance.
Use your paint like this:
Paint x = Paint()
..style = PaintingStyle.fill
..maskFilter = MaskFilter.blur(BlurStyle.inner, 5)
..color = Colors.grey;
Output:
I propose the same approach as given in my other answer. In your case you just use the CustomPaint widget as the child for the inner shadow widget:
InnerShadow(
shadow: const BoxShadow(
blurRadius: 20,
color: Colors.black,
),
child: CustomPaint(painter: TitleContainerPaint()),
)
The complete code could be found here https://codepen.io/priezz/pen/abBRmrb
P.S. Your TitleContainerPaint gives slightly different shape than given in your example image, you'll probably need to tweak it. Maybe it's just the issue with Flutter for Web.
//change the alpha color of your grey color like this
canvas.drawShadow(path, Colors.grey.withAlpha(50), -4.0, false);
Here the shadow will be inner.

how to create custom chart in flutter

i am trying to create chart like this that has a circular border
i want to create custom like this/
how i am gonna do that , is there any packages that i can modify it and make it like this
If you want to create a chart, you can use syncfusion_flutter_charts
and if you want create curves you can use CustomPaint widget. one example I find in my code for you:
CustomPaint(
painter: CurveBackground(color: \\ yourColor),
child: \\ your child
)
class CurveBackground extends CustomPainter {
final Color color;
CurveBackground({this.color});
#override
void paint(Canvas canvas, Size size) {
var paint = Paint();
paint.color = color;
paint.style = PaintingStyle.fill;
var path = Path();
path.moveTo(0, Dimens.size_30());
path.quadraticBezierTo(size.width * 0.4, size.height * 0.1,
size.width * 0.3, size.height * 0.3);
path.quadraticBezierTo(size.width * 0.1, size.height * 0.6,
size.width * 0.45, size.height * 0.7);
path.quadraticBezierTo(
size.width * 1, size.height * 0.9, size.width * 0.9, size.height * 1.0);
path.lineTo(size.width, size.height);
path.lineTo(0, size.height);
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) => true;
}

Fllutter - How to create a custom shape

the bellow image that is what i want to draw it using CustomPainter with LinearGradient and have shadow
already i draw bellow circle shape but not same and have LinearGradient
class CurvePainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
Rect rect = new Rect.fromCircle(
center: new Offset(165.0, 55.0),
radius: 180.0,
);
final Gradient gradient = new LinearGradient(
colors: <Color>[
const Color(0xFF2151a6),
const Color(0xFF3377f4),
],
);
var paint = Paint()..shader = gradient.createShader(rect);
paint.color = Colors.green[800];
paint.style = PaintingStyle.fill; // Change this to fill
var path = Path();
path.moveTo(0, size.height * 0.35);
path.moveTo(0, size.height * 0.3);
path.quadraticBezierTo(
size.width / 2, size.height / 2.4, size.width, size.height * 0.35);
path.lineTo(size.width, 0);
path.lineTo(0, 0);
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
I think I drew it well
try this:
class CurvePainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
Rect rect = new Rect.fromCircle(
center: new Offset(165.0, 55.0),
radius: 180.0,
);
final Gradient gradient = new LinearGradient(
colors: <Color>[
const Color(0xFF2151a6),
const Color(0xFF3377f4),
],
);
var paint = Paint()..shader = gradient.createShader(rect);
paint.color = Colors.green[800];
paint.style = PaintingStyle.fill; // Change this to fill
var path = Path();
path.moveTo(0, size.height * 0.32);
path.lineTo(size.width * 0.20, size.height * 0.34);
path.quadraticBezierTo( size.width * 0.30, size.height * 0.35,
size.width * 0.40, size.height * 0.34 );
path.lineTo(size.width*0.9, size.height * 0.26);
path.quadraticBezierTo( size.width, size.height * 0.24,
size.width , size.height * 0.20);
path.lineTo(size.width, 0);
path.lineTo(0 , 0);
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}

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?
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;
}
}
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.
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.