I'm trying to draw this oval in Custom Painter.
I can't seem to wrap my head around it. I've tried using the drawOval() function on the Canvas:
#override
void paint(Canvas canvas, Size size) {
final startAngle = -math.pi / 2;
final sweepAngle = math.pi;
Offset center = Offset(size.width * 0.5, size.height * 0.5);
int lineAmount = 10;
Color paintColor = Color.fromRGBO(250, 154, 210, 1);
Paint circlePaint = Paint()
..color = paintColor
..style = PaintingStyle.stroke
..strokeWidth = 5;
// HIGHLIGHT
canvas.drawOval(Rect.fromLTRB(50, 100, 250, 200), circlePaint);
}
... and using the drawArc() function:
canvas.drawArc(Rect.fromLTRB(50, 100, 250, 200), startAngle, sweepAngle,
false, circlePaint);
canvas.drawArc(Rect.fromLTRB(50, 100, 250, 200), -startAngle, -sweepAngle,
false, circlePaint);
This is the result I keep on getting:
How can I properly draw the arc?
as an option you can use canvas transformations - translate and rotate
like this:
#override
void paint(Canvas canvas, Size size) {
final angle = -math.pi / 4;
Color paintColor = Color.fromRGBO(250, 154, 210, 1);
Paint circlePaint = Paint()
..color = paintColor
..style = PaintingStyle.stroke
..strokeWidth = 5;
canvas.save();
canvas.translate(size.width * 0.5, size.height * 0.5);
canvas.rotate(angle);
canvas.drawOval(Rect.fromCenter(center: Offset.zero, width: 50, height: 100), circlePaint);
canvas.restore();
}
Related
I made a custom shape of a crooked square for music artwork images, now I'm trying to make the image fill it completely whilst not leaking out of it.
I tried using a stack, but it is bugging the painted square and the image still would leak and not fill it completely.
SizedBox(
width: 50,
height: 50,
child: CustomPaint(
painter: ImperfectRectangleBorder(strokeColor: Colors.white),
child: QueryArtworkWidget(//from on_audio_query package
artworkBorder: BorderRadius.zero,
artworkFit: BoxFit.fill,
id: item.data![index].id,
type: ArtworkType.AUDIO,
),
),
),
class ImperfectRectangleBorder extends CustomPainter {
final Color strokeColor;
ImperfectRectangleBorder({this.strokeColor = Colors.white});
#override
void paint(Canvas canvas, Size size) {
var paint = Paint()
..color = strokeColor
..strokeWidth = 4.0
..style = PaintingStyle.stroke;
var path = Path();
path.moveTo(0, -5);
path.lineTo(size.width * (0.2), size.height + 10);
path.lineTo(size.width, size.height - 5);
path.lineTo(size.height * (0.8), -1);
path.close();
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) {
return false;
}
}
I have below custom painter and I want to round any edge of the path
I will be grateful if you help
you can use this CustomPainter:
class CustomDraw extends CustomPainter {
late Paint painter;
late double radius;
CustomDraw(Color color, {this.radius = 0}) {
painter = Paint()
..style = PaintingStyle.stroke
..strokeWidth = 10
..strokeCap = StrokeCap.round
..color = color;
}
#override
void paint(Canvas canvas, Size size) {
var path = Path();
path.moveTo(size.width, 0);
path.lineTo(0 + radius, 0);
path.cubicTo(0 + radius, 0, 0, 0, 0, radius);
path.lineTo(0, 35 - radius);
path.cubicTo(0, 35 - radius, 0, 35, radius, 35);
path.lineTo(size.width - radius, 35);
path.cubicTo(
size.width - radius, 35, size.width, 35, size.width, 35 + radius);
path.lineTo(size.width, 35 + 35 - radius);
path.cubicTo(size.width, 35 + 35 - radius, size.width, 35 + 35,
size.width - radius, 35 + 35);
path.lineTo(0, 35 + 35);
canvas.drawPath(path, painter);
}
#override
bool shouldRepaint(covariant CustomPainter oldDelegate) => false;
}
use it like this:
CustomPaint(
painter: CustomDraw(Colors.red, radius: 16),
child: SizedBox(
height: 100,
width: 200,
),
),
I am trying to draw the following shape using CustomPainter, I am looking for a way
to make this shape as one shape (union), so for example using Stack with Container and half circle shape is not desired.
I have managed to paint the base rectangular shape as the following image shows, is it possible to build on top of this code to draw a half a circle in the middle ?
Container(
height: 85,
color: Colors.blueGrey,
child: Stack(
children: [
CustomPaint(
size: Size(size.width, 85),
painter: MyCustomPainter(),
)
],
),
),
class MyCustomPainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
var paint = Paint()
..color = Colors.red
..style = PaintingStyle.fill;
var path = Path()..moveTo(0, 20);
path.quadraticBezierTo(0, 0, 0, size.height * 0.5);
path.quadraticBezierTo(0, 0, size.width * 0.2, 0);
path.quadraticBezierTo(size.width, 0, size.width * 0.8, 0);
path.quadraticBezierTo(size.width, 0, size.width, size.height * 0.5);
path.lineTo(size.width, size.height);
path.lineTo(0, size.height);
canvas.drawPath(path, paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}
While the question about using union operation, I am focusing on
canvas.drawPath(
Path.combine(PathOperation.union, path1, circlePath), paint);
The current paint takes full height and doesnt maintain the ration based on your desire result. I am using Rect on Path to demonstrating the union operation. Change the size/value according to your needs.
class MyCustomPainter extends CustomPainter {
#override
void paint(Canvas canvas, Size size) {
var paint = Paint()
..color = Colors.red
..style = PaintingStyle.fill;
final double base = size.height * .4;
const corner = Radius.circular(16);
final path1 = Path()
..addRRect(
RRect.fromLTRBAndCorners(0, base, size.width, size.height,
topLeft: corner, topRight: corner),
);
final center = Offset(size.width / 2, size.height / 2);
final radius = size.height / 2;
final circlePath = Path()
..addOval(Rect.fromCircle(center: center, radius: radius));
canvas.drawPath(
Path.combine(PathOperation.union, path1, circlePath), paint);
}
#override
bool shouldRepaint(CustomPainter oldDelegate) => false;
}
More about CustomPaint
I created a custom widget in flutter using custom painter. Its a status bar. I wanted to animate it, but now a problem is occurring that I don't know how to fix.
The bar consists of a line and several dots, depending on the status. When animating this bar, the line is correctly animated, but the dot is appearing to early, it just pops in.
example of how my widget is currently animating (can't post inline yet)
How can I choose when the dot animates?
This is the code I use for animating my widget:
class _StatusBarState extends State<StatusBar> with TickerProviderStateMixin {
late AnimationController _animationController;
#override
void initState() {
super.initState();
_animationController = AnimationController(
vsync: this,
duration: Duration(seconds: 1),
lowerBound: 1,
upperBound: widget.states.length.toDouble());
}
#override
void didUpdateWidget(covariant StatusBar oldWidget) {
super.didUpdateWidget(oldWidget);
_animationController.animateTo(widget.currentState.toDouble());
}
#override
Widget build(BuildContext context) {
return Column(
children: [
AnimatedBuilder(
animation: _animationController,
builder: (BuildContext buildContext, Widget? child) => Container(
height: 50,
width: MediaQuery.of(context).size.width * 0.75,
child: CustomPaint(
painter: _RentalStatusBarPainter(
context: context,
currentState: _animationController.value,
states: widget.states,
failed: widget.error),
),
),
),
Container(
width: MediaQuery.of(context).size.width * 0.85,
child: Row(
mainAxisAlignment: MainAxisAlignment.spaceBetween,
children: widget.states
.map((e) => widget.states.indexOf(e) == widget.currentState - 1
? Text(
e,
style: Theme.of(context).textTheme.subtitle1,
)
: Text(
e,
style: Theme.of(context).textTheme.caption,
))
.toList(),
),
),
SizedBox(height: 10),
],
);
}
}
And this is the custom widget that is being painted:
#override
void paint(Canvas canvas, Size size) {
int currentStateInt = currentState.toInt();
final paint = Paint()
..color = Theme.of(context).cardColor
..style = PaintingStyle.stroke
..strokeWidth = 5
..strokeCap = StrokeCap.round;
final dotspaint = Paint()
..color = Theme.of(context).cardColor
..style = PaintingStyle.fill;
final filledpaint = Paint()
..color = failed
? Theme.of(context).colorScheme.error
: Theme.of(context).colorScheme.secondary
..style = PaintingStyle.stroke
..strokeWidth = 5
..strokeCap = StrokeCap.round;
final filleddotspaint = Paint()
..color = failed
? Theme.of(context).colorScheme.error
: Theme.of(context).colorScheme.secondary
..style = PaintingStyle.fill
..strokeCap = StrokeCap.round;
//draw the background
canvas.drawLine(
Offset(0, size.height / 2),
Offset(size.width, size.height / 2),
paint,
);
for (int i = 0; i < numberOfStates; i++) {
final double x = size.width * i / (numberOfStates - 1);
canvas.drawCircle(Offset(x, size.height / 2), 10, dotspaint);
}
//draw the filled out stuff
canvas.drawLine(
Offset(0, size.height / 2),
Offset(size.width * (currentState - 1) / (numberOfStates - 1),
size.height / 2),
filledpaint,
);
for (int i = 0; i < currentState; i++) {
final double x = size.width * i / (numberOfStates - 1);
canvas.drawCircle(Offset(x, size.height / 2), 10, filleddotspaint);
}
}
Any ideas or insights into how this "automatic" animation actually works is deeply appreciated!
Anton
I actually found a workaround for this, and have an assumption of why my circles were not animated:
for (int i = 0; i < currentState - 1; i++) {
final double x = size.width * i / (numberOfStates - 1);
canvas.drawCircle(Offset(x, size.height / 2), 10, filleddotspaint);
}
final double x = size.width * (currentState - 1) / (numberOfStates - 1);
canvas.drawCircle(Offset(x, size.height / 2), 10, filleddotspaint);
I changed the last circle to be drawn outside of the for loop. This seems to be enough for the framework to detect that this is something that it should animate. Maybe the for loop confused it in some way?
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;
}
}