how to create custom chart in flutter - 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;
}

Related

How to draw Image Inside Circulr path in Canvas in Flutter

Hello can anyone tell me how can i draw image inside circular path with scaled image that fits inside the path. I tried but could not able to figure out and bothering a lot. Please help me.
Paint paint_4 = new Paint()
..color = Colors.black
..style = PaintingStyle.fill
..strokeWidth = 1;
Path path_4 = Path();
path_4.moveTo(size.width * 0.2275000, size.height * 0.2879286);
path_4.cubicTo(
size.width * 0.2528667,
size.height * 0.2879286,
size.width * 0.2928750,
size.height * 0.3193143,
size.width * 0.2928750,
size.height * 0.4000000);
path_4.cubicTo(
size.width * 0.2928750,
size.height * 0.4449143,
size.width * 0.2733667,
size.height * 0.5120714,
size.width * 0.2275000,
size.height * 0.5120714);
path_4.cubicTo(
size.width * 0.2013083,
size.height * 0.5120714,
size.width * 0.1621250,
size.height * 0.4786286,
size.width * 0.1621250,
size.height * 0.4000000);
path_4.cubicTo(
size.width * 0.1621250,
size.height * 0.3550857,
size.width * 0.1808750,
size.height * 0.2879286,
size.width * 0.2275000,
size.height * 0.2879286);
path_4.close();
Circular Path to draw Image and Image need to be properly Scaled to
be visible
How Can I Scale assest image to Circular path in properly visibe or fit
How can i use Matrix4 to scale ImageShader to canvas
canvas.drawPath(
path_4,
Paint()
..shader = ImageShader(images, TileMode.clamp,TileMode.clamp,Matrix4.identity().scaled(0.19, 0.21).storage));
Here Is my Code
class ImagePainters extends StatefulWidget {
#override
_ImagePaintersState createState() => _ImagePaintersState();
}
class _ImagePaintersState extends State<ImagePainters> {
ui.Image myImage;
Future<ui.Image> _loadAssetImage() async {
Completer<ui.Image> completer = new Completer<ui.Image();
AssetImage('assets/face.jpg').resolve(new ImageConfiguration()).addListener(
ImageStreamListener((ImageInfo image, bool synchronousCall) {
setState(() {
myImage = image.image;
});
ui.Image img;
img = image.image;
completer.complete(img);
}));
return completer.future;
}
#override
void initState() {
super.initState();
_loadAssetImage();
}
#override
Widget build(BuildContext context) {
return Center(
child: Container(
height: MediaQuery.of(context).size.height,
width: MediaQuery.of(context).size.width,
child: CustomPaint(
size: Size(1000, 1000 * 0.7),
painter: FinalPainter(context, myImage)),
),
);
}
}
Canvas Drawing Class
class FinalPainter extends CustomPainter {
final ui.Image images;
FinalPainter(BuildContext context, this.images);
#override
void paint(Canvas canvas, Size size) {
Paint paint_4 = new Paint()
..color = Colors.black //Color.fromARGB(255, 255, 255, 255)
..style = PaintingStyle.fill
..strokeWidth = 1;
Path path_4 = Path();
path_4.moveTo(size.width * 0.2275000, size.height * 0.2879286);
path_4.cubicTo(
size.width * 0.2528667,
size.height * 0.2879286,
size.width * 0.2928750,
size.height * 0.3193143,
size.width * 0.2928750,
size.height * 0.4000000);
path_4.cubicTo(
size.width * 0.2928750,
size.height * 0.4449143,
size.width * 0.2733667,
size.height * 0.5120714,
size.width * 0.2275000,
size.height * 0.5120714);
path_4.cubicTo(
size.width * 0.2013083,
size.height * 0.5120714,
size.width * 0.1621250,
size.height * 0.4786286,
size.width * 0.1621250,
size.height * 0.4000000);
path_4.cubicTo(
size.width * 0.1621250,
size.height * 0.3550857,
size.width * 0.1808750,
size.height * 0.2879286,
size.width * 0.2275000,
size.height * 0.2879286);
path_4.close();
Image should be properly visible and can be scaled Circular Path to
draw Image and Image need to be properly Scaled to be visible
Face should be visible clearly inside the circular path
canvas.drawPath(path_4, Paint()..shader = ImageShader(images,
TileMode.clamp, TileMode.clamp,
Matrix4.identity().scaled(0.19, 0.21).storage));}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
{return true;}
}

Flutter reverse clipper direction

I need to show triangle type shape container which is almost complete but there is one issue its showing the triangle shape in opposite direction my code
class ClipPathClass extends CustomClipper<Path> {
#override
Path getClip(Size size) {
var roundnessFactor = 50.0;
var path = Path();
path.moveTo(0, size.height * 0.33);
path.lineTo(0, size.height - roundnessFactor);
path.quadraticBezierTo(0, size.height, roundnessFactor, size.height);
path.lineTo(size.width - roundnessFactor, size.height);
path.quadraticBezierTo(
size.width, size.height, size.width, size.height - roundnessFactor);
path.lineTo(size.width, roundnessFactor * 2);
path.quadraticBezierTo(size.width - 10, roundnessFactor,
size.width - roundnessFactor * 1.5, roundnessFactor * 1.5);
path.lineTo(
roundnessFactor * 0.6, size.height * 0.33 - roundnessFactor * 0.3);
path.quadraticBezierTo(
0, size.height * 0.33, 0, size.height * 0.33 + roundnessFactor);
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
This is how i am showing this
ClipPath(
clipper: RoundedDiagonalPathClipper(),
child: Container(
height: 320,
decoration: BoxDecoration(
borderRadius: BorderRadius.all(Radius.circular(30.0)),
color: Colors.orange,
),
child: null,
),
),
Out put is showing like this
But i need to show the upper part like this just reverse it. I play with everything but it's not reversing.
I implemented _getY function so that there is no bend in the corner. And I added an equalization variable to make look better.
Reference: Paths in Flutter: A Visual Guide.
Screenshot
RoundedDiagonalPathClipper.dart
class RoundedDiagonalPathClipper extends CustomClipper<Path> {
double _getY(double x) {
return x * 0.33;
}
#override
Path getClip(Size size) {
var roundnessFactor = 50.0;
var equalization = 10.0;
var path = Path();
path.moveTo(0, roundnessFactor);
path.lineTo(0, size.height - roundnessFactor);
path.quadraticBezierTo(0, size.height, roundnessFactor, size.height);
path.lineTo(size.width - roundnessFactor, size.height);
path.quadraticBezierTo(
size.width, size.height, size.width, size.height - roundnessFactor);
path.lineTo(size.width, _getY(size.width) + roundnessFactor - equalization);
path.quadraticBezierTo(
size.width,
_getY(size.width),
size.width - roundnessFactor + equalization,
_getY(size.width - roundnessFactor + equalization));
path.lineTo(
roundnessFactor + equalization, _getY(roundnessFactor + equalization));
path.quadraticBezierTo(0, 0, 0, roundnessFactor + equalization);
return path;
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
Edit: Adding shadow
I made the shadow version by using the gist:coman3-ClipShadowPath.dart.
ClipShadowPath.dart
#immutable
class ClipShadowPath extends StatelessWidget {
final Shadow shadow;
final CustomClipper<Path> clipper;
final Widget child;
ClipShadowPath({
required this.shadow,
required this.clipper,
required this.child,
});
#override
Widget build(BuildContext context) {
return CustomPaint(
key: UniqueKey(),
painter: _ClipShadowShadowPainter(
clipper: this.clipper,
shadow: this.shadow,
),
child: ClipPath(child: child, clipper: this.clipper),
);
}
}
class _ClipShadowShadowPainter extends CustomPainter {
final Shadow shadow;
final CustomClipper<Path> clipper;
_ClipShadowShadowPainter({required this.shadow, required this.clipper});
#override
void paint(Canvas canvas, Size size) {
var paint = shadow.toPaint();
var clipPath = clipper.getClip(size).shift(shadow.offset);
canvas.drawPath(clipPath, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
Usage
ClipShadowPath(
shadow: Shadow(blurRadius: 20.0, color: Colors.black54),
clipper: RoundedDiagonalPathClipper(),
child: Container(color: Colors.orange),
)
just apply Matrix transformation on Path, so you will free to do any changes on path, it will flip vertically any path
how to use:
clipper: ClipPathClass(),
or if need to reverse
clipper: ClipPathClass(flip: true),
class ClipPathClass extends CustomClipper<Path> {
final roundnessFactor = 50.0;
final bool flip;
ClipPathClass({this.flip = false});
#override
Path getClip(Size size) {
final path = Path();
path.moveTo(0, size.height * 0.33);
path.lineTo(0, size.height - roundnessFactor);
path.quadraticBezierTo(0, size.height, roundnessFactor, size.height);
path.lineTo(size.width - roundnessFactor, size.height);
path.quadraticBezierTo(size.width, size.height, size.width, size.height - roundnessFactor);
path.lineTo(size.width, roundnessFactor * 2);
path.quadraticBezierTo(size.width - 10, roundnessFactor, size.width - roundnessFactor * 1.5, roundnessFactor * 1.5);
path.lineTo(roundnessFactor * 0.6, size.height * 0.33 - roundnessFactor * 0.3);
path.quadraticBezierTo(0, size.height * 0.33, 0, size.height * 0.33 + roundnessFactor);
return flip ? _flip(path, size.width) : path;
}
Path _flip(Path path, double width) {
final m = Matrix4.identity()
..translate(width)
..rotateY(math.pi);
return path.transform(m.storage);
}
#override
bool shouldReclip(CustomClipper<Path> oldClipper) => false;
}
I won't explain the change line by line, I tried to keep the round corner uniform on the four corners.
Here your are:
class RoundedDiagonalPathClipper extends CustomClipper<Path> {
#override
Path getClip(Size size) {
var roundnessFactor = 50.0;
var path = Path();
path.moveTo(0, roundnessFactor);
path.lineTo(0, size.height - roundnessFactor);
path.quadraticBezierTo(0, size.height, roundnessFactor, size.height);
path.lineTo(size.width - roundnessFactor, size.height);
path.quadraticBezierTo(
size.width, size.height, size.width, size.height - roundnessFactor);
path.lineTo(size.width, size.height * 0.33 + roundnessFactor * 0.5);
path.quadraticBezierTo(
size.width,
size.height * 0.33,
size.width - roundnessFactor,
size.height * 0.33 - roundnessFactor * 0.5);
path.lineTo(roundnessFactor, 0);
path.quadraticBezierTo(0, 0, 0, roundnessFactor);
return path;
}
The result will be this one:

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.

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.