When I draw lines on a CustomPainter's canvas using code like this:
var paint = Paint()
..style = PaintingStyle.stroke
..strokeWidth = 4.0
..color = Colors.grey;
canvas.drawLine(fromOffsetA, toOffsetB, paint);
canvas.drawLine(fromOffsetC, toOffsetD, paint);
If the two lines partly overlap over one another, then the section of the lines that overlap show the line color as being darker than in the sections of the line that do not overlap.
I am guessing that this is by design so, my question is, how do I draw lines that overlap one another and at the same time prevent the lines' color from darkening in the overlapped sections?
I am thinking I need to set the paint's Blendmode to a specific value or something along those lines?
Related
I am attempting to figure out the most efficient way to draw lines with the CustomPainter widget.
I have everything set up and it works great as I pass in points to the custompainter and it paints all of the lines perfectly using this class:
class MyPainter extends CustomPainter {
List<Offset?> points;
MyPainter({required this.points});
#override
void paint(Canvas canvas, Size size) {
Paint background = Paint()..color = Colors.grey.shade50;
Rect rect = Rect.fromLTWH(0, 0, size.width, size.height);
canvas.drawRect(rect, background);
Paint paint = Paint()
..color = Colors.black
..strokeCap = StrokeCap.round
..strokeWidth = 3;
for(int i = 0; i < points.length - 1; i++){
if(points[i] != null && points[i + 1] != null){
canvas.drawLine(points[i]!, points[i + 1]!, paint);
}
else if (points[i] != null && points[i + 1] == null){
canvas.drawPoints(PointMode.points, [points[i]!], paint);
}
}
}
#override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
My issue becomes apparent when the number of points becomes increasingly larger with time. I have 2 dials that the user spins and every frame it changes the "cursor" position based on the dial that is being spun for dx and dy respectively. Every time the dial changes it's angle and the cursor position changes this function is called:
void cursorChange(double distanceX, double distanceY){
setState(() {
cursor = Offset(distanceX, distanceY);
points.add(cursor);
points = removeDuplicatePoints(points);
});
}
Which repaints the canvas appropriately based on the points list. When this list becomes bigger it lowers performance when it really shouldn't. For example if I rotated the left dial 100 degrees, it would move the cursor to the right by 100, which should draw a line from origin to where the cursor is. Logically, because it's a line you'd only need 2 points, but because I have to redraw the new line at the new cursor spot, my logic just adds another point resulting into like 200 points for one line. It is most easiest to imagine this like an etch-a-sketch game!
In Short: I need to find an algorithm that optimally draws different lines while ignoring any points that are on an existing line.
I have tried just removing all of the points in between the origin and the current cursor to make the line but the user can also move vertically creating a new line. 2 things prevent this solution:
The user can move backwards too and deleting the points in between would just remove the furthest point and make it smaller.
If the user moved the dial vertically, the line would just rotate to the cursor
I then tried to patch these issues with some conditionals to check for direction, then add a null point and treat it like a new origin. This only led me down a game of cat and mouse that seemed to never end.
Any help would be so incredibly appreciated.
I am using canvas to draw circles in flutter, is there any easy way to draw circles filled with lines?
PS:I know I can calculate each line's points then drawing lines in circle. But is there any simple method that can be implemented without calculation?
This is what I want to achieve:
Finally, I found an easy and ingenious solution without calculation.
That is creating a linear gradient filled in the circle.
give two colors for the start and end of the gradient.
give transparent to the start color.
give the actual line color to the end color.
Paint paint = new Paint();
paint.color =Colors.red;
paint.style = PaintingStyle.fill;
paint.shader = ui.Gradient.linear(
start,
//the line interval is 20
Offset(start.dx + 20, start.dy),
[
//give transparent to start color, give actual line color to the end color
Colors. transparent,
Colors.red
],
//The interval [0.0,0.9] is transparent, and the interval [0.9,1.0] is red. So it looks like drawing red lines
[0.90, 1.0],
//just repeat the gradient
TileMode.repeated,
null);
canvas.drawCircle(
Offset(centerX, centerY),
radius,
paint);
I'm learning CustomPaint by making my own line chart. I have already made the chart itself so now i'm making the things around it. One them is a trackball/line whenever you pan. So far i've made the dashed line from top to bottom, and it works perfectly, now i want to make the the ball that's gonna follow along with the line. My problem is getting the ball and dashed line to always be in sync. right now it's the dashed line that follows my finger and the ball that does'nt match up. I found this answer on stack overflow but it's not working quite right for me. This video is how it currently functions with the following code,
where dragX is the current x-axis position of your finger in pixels.
void drawTrackballLine(Canvas canvas, Size size) {
double dashHeight = 5;
double dashSpace = trackBallOptions.dashSpacing;
double y = 0;
final paint = Paint()
..color = trackBallOptions.color
..strokeWidth = trackBallOptions.strokeWidth;
while (y < size.height) {
canvas.drawLine(
Offset(dragX, y),
Offset(dragX, y + dashHeight),
paint,
);
y += dashSpace + dashHeight;
}
}
void drawTrackball(Canvas canvas, Size size, Path path) {
final pathMetric = path.computeMetrics().elementAt(0);
final value = pathMetric.length * (dragX / size.width);
final pos = pathMetric.getTangentForOffset(value);
canvas.drawCircle(pos!.position, 5, Paint());
}
Is there a way to choose a color to be replaced for transparent when painting an image to the Flutter canvas? I have a spritesheet with magenta background and I want it to be transparent when painted. I am painting in the following way:
void _draw(Canvas canvas, Offset offset, ui.Image image) {
final paint = Paint();
canvas.drawImage(image, offset, paint);
}
You just need to set an ARGB color with the alpha value
paint.color = Color.fromARGB(alpha, r, g, b)
Where alpha is a double between 0 and 1, 0 being transparent and 1 the most visible. R,G,B is the level of red blue green colors applied.
The white color is:
r=255, g=255, b=255
The black color is:
r=0, g=0, b=0
So in your case:
paint.color = Color.fromARGB(0, 0, 0, 0)
How to draw a filled polygon in flutter?
Currently I am able to a eyebrow shape with array of point like below.
Path leftEyePath = Path();
leftEyePath.moveTo(leftEye[0].getX(),leftEye[0].getY());//starting point
for(int i=1;i<leftEye.length;i++){
leftEyePath.lineTo(leftEye[i].getX(),leftEye[i].getY());
}
canvas.drawPath(leftEyePath,painter);
The code above will eventually draw a connected polygon with many line , but how do I draw a filled polygon with color I want?
EDIT:
I am currently go through their function and found drawShadow(..)
canvas.drawShadow(leftEyePath, Colors.orange[600],0,true);
Unfortunately it only draw transparent color.
Below is my current output.
You may change your paint style into PaintingStyle.fill. The paint brush will automatically fill up the closing area of your path.
Paint _filledPainter = new Paint()
..style = PaintingStyle.fill
;