The foreword 0.
A lot of people ask me how to draw dotted lines, but I have no need for this aspect, I do not care too much. Now that you think about it, drawing dashed lines through path measurements should be pretty simple. I will spare some space and write a handy dotted line path drawing tool, otherwise it is really quite laborious to draw an auxiliary line.
The painting tool dash_painter has been uploaded to pub:
- Dev /packages/da…
- Github address: github.com/toly1994328…
The rounded rectangle | circular |
---|---|
1. Implementation of the drawing
In the following palette, I draw a line through a path, which is probably the most basic thing to draw. Now let’s see how we can do that and turn it into a dotted line.
class TolyPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
canvas.translate(size.width / 2, size.height / 2); Paint paint = Paint().. style = PaintingStyle.stroke .. color=Colors.orangeAccent.. strokeWidth =2;
Path path = Path();
path.moveTo(- 100..0);
path.lineTo(100.0);
canvas.drawPath(path, paint);
}
@override
bool shouldRepaint(covariant TolyPainter oldDelegate) => false;
}
Copy the code
2. Draw a dotted line – Level1
For ease of administration and extension, you can separate the dashed object into a class DashPainter. So if you want to draw a dotted line, you have to specify the dotted line parameters, so let’s do a simple one. The single length and spacing of the dotted line are represented by step and span respectively. The following is a dotted line with step:20 and span: 10.
class DashPainter {
final double step;
final double span;
const DashPainter({this.step = 2.this.span = 2});double get partLength => step + span;
void paint(Canvas canvas, Path path, Paint paint) {
final PathMetrics pms = path.computeMetrics();
pms.forEach((PathMetric pm) {
final int count = pm.length ~/ partLength;
for (int i = 0; i < count; i++) {
canvas.drawPath(
pm.extractPath(partLength * i, partLength * i + step), paint);
}
final doubletail = pm.length % partLength; canvas.drawPath(pm.extractPath(pm.length-tail, pm.length), paint); }); }}Copy the code
The implementation logic is also very simple: computeMetrics the path, and then according to the number of copies traversal to draw the intercepted path. It is also very simple to use, as long as a sentence can be changed into virtual:
const DashPainter(span: 10, step: 20).paint(canvas, path, paint);
Copy the code
You can control the display of dashed lines by controlling the step and SPAN parameters.
step:6, span: 6 | step:6, span: 4 |
---|---|
In fact, at this point, you can make any path dotted, rounded rectangle and circle as follows:
final Path path = Path();
path.addRRect(RRect.fromRectAndRadius(
Rect.fromCircle(center: Offset.zero, radius: 100),
Radius.circular(20)));const DashPainter(span: 4, step: 9).paint(canvas, path, paint);
Copy the code
The rounded rectangle | circular |
---|---|
2. Draw a dotted line – Level2
In addition to dotted lines, sometimes there is a requirement for underlined lines, as follows
Single point line
:
Two point line
:
Three-point line
:
Add pointCount and pointWidth to the pointCount and pointWidth attributes, respectively. The pointLineLength length should be lengthened according to pointCount and pointWidth, as shown below:
class DashPainter {
const DashPainter({
this.step = 2.this.span = 2.this.pointCount = 0.this.pointWidth,
});
final double step;
final double span;
final int pointCount;
final double pointWidth;
void paint(Canvas canvas, Path path, Paint paint) {
final PathMetrics pms = path.computeMetrics();
final double pointLineLength = pointWidth ?? paint.strokeWidth;
final double partLength =
step + span * (pointCount + 1) + pointCount * pointLineLength;
pms.forEach((PathMetric pm) {
final int count = pm.length ~/ partLength;
for (int i = 0; i < count; i++) {
canvas.drawPath(
pm.extractPath(partLength * i, partLength * i + step), paint,);
for (int j = 1; j <= pointCount; j++) {
final start =
partLength * i + step + span * j + pointLineLength * (j - 1); canvas.drawPath( pm.extractPath(start, start + pointLineLength), paint, ); }}final doubletail = pm.length % partLength; canvas.drawPath(pm.extractPath(pm.length - tail, pm.length), paint); }); }}Copy the code
This allows you to do cool things like dot lines and circles:
final Path path = Path();
path.moveTo(- 200..0);
path.lineTo(200.0);
path.moveTo(0.- 200.);
path.lineTo(0.200);
path.addOval(Rect.fromCircle(center: Offset.zero, radius: 100));
const DashPainter(
span: 4./ / space
step: 10./ / solid lines long
pointCount: 2.// Number of dashes
pointWidth: 2 // The dashes are long
).paint(canvas, path, paint);
Copy the code
3. Decoration drawing
Many people may not be able to customize their own artboards or simply want to use them. In fact, there are other places besides CustomPainter that have canvas. Such as Decoration. We can customize the decoration of DashDecoration for easy use. This is just a simple use to encapsulate the configuration properties.
class DashDecoration extends Decoration {
@override
BoxPainter createBoxPainter([onChanged]) => const DashBoxPainter();
}
class DashBoxPainter extends BoxPainter {
final Color color;
const DashBoxPainter({this.color});
@override
void paint(Canvas canvas, Offset offset, ImageConfiguration configuration) {
canvas.save();
finalPaint paint = Paint() .. style = PaintingStyle.stroke .. color = Colors.orangeAccent .. strokeWidth =1;
final Path path = Path();
canvas.translate(
offset.dx + configuration.size.width / 2,
offset.dy + configuration.size.height / 2,);final Rect zone = Rect.fromCenter(
center: Offset.zero,
width: configuration.size.width,
height: configuration.size.height,
);
path.addRRect(RRect.fromRectAndRadius(
zone,
Radius.circular(20)));const DashPainter(span: 4, step: 9).paint(canvas, path, paint); canvas.restore(); }}Copy the code
This property configuration is packaged in the library and can be used directly, as shown in the following implementation of a gradient single dotted line rounded dotted box.
Container(
width: 100,
height: 100,
decoration: DashDecoration(
pointWidth: 2,
step: 5,
pointCount: 1,
radius: Radius.circular(15),
gradient: SweepGradient(colors: [
Colors.blue,
Colors.red,
Colors.yellow,
Colors.green
])),
child: Icon(
Icons.add,
color: Colors.orangeAccent,
size: 40,),),Copy the code
This article ends here, this tool has a lot of room to optimize and expand, later sometimes or inspiration will continue to maintain, I hope to help you.