Flutter学习:认识CustomPaint组件和Paint对象
Flutter学习:使用CustomPaint绘制路径
Flutter学习:使用CustomPaint绘制图形
Flutter学习:使用CustomPaint绘制文字
Flutter学习:使用CustomPaint绘制图片
drawPath需要传递2个参数:
dart
复制代码
Path path = Path()..moveTo(100, 100); path.lineTo(250, 250); path.lineTo(350, 180); path.lineTo(200, 500); // 控制路径是否闭合,可不写 path.close(); canvas.drawPath(path, paint);
path.moveTo和path.lineTo一样,都需要传递2个参数:
dart
复制代码
path.moveTo(80, 200); path.lineTo(320, 400); canvas.drawPath(path, paint);
其中p0是path.moveTo设置的坐标,p1是path.lineTo设置的坐标
path.relativeMoveTo和path.relativeLineTofiType的使用方法和path.moveTo、path.lineTo一样,只是起始点不再是左上角,而是前一个点的坐标
用来设置路径是否自己闭合:
dart
复制代码
path.close();
清除之前所有的Path对象。并重置原点为左上角。
dart
复制代码
path.reset();
关于fillType的资料可以查看以下文章:
fillType有两个枚举值:
dart
复制代码
Path path = Path()..moveTo(size.width / 2, 200); path.lineTo(size.width / 4, 500); path.lineTo(size.width / 7 * 6, 320); path.lineTo(size.width / 7, 320); path.lineTo(size.width / 4 * 3, 500); path.close(); // 默认值 path.fillType = PathFillType.nonZero; path.fillType = PathFillType.evenOdd; canvas.drawPath(path, paint);
通过路径绘制圆弧
addArc(Rect oval, double startAngle, double sweepAngle)
需要传递3个参数:
dart
复制代码
// 只有path.addArc方法,path.moveTo方法将会无效 Path path = Path(); // path.moveTo(size.width / 2, 200); 无效 Rect oval = Rect.fromPoints(const Offset(80, 80), const Offset(300, 180)); path.addArc(oval, 0, 4); canvas.drawPath(path, paint);
dart
复制代码
// 有path.moveTo、path.lineTo、path.addArc这3个方法 // path.lineTo在谁的后面就跟谁连接,默认path.moveTo为(0,0) Path path = Path(); path.moveTo(size.width / 2, 200); Rect oval = Rect.fromPoints(const Offset(80, 80), const Offset(300, 180)); path.addArc(oval, 0, 4); path.lineTo(250, 400); canvas.drawPath(path, paint);
该方法将复制一遍已绘制的路径,并进行偏移
addPath(Path path, Offset offset, {Float64List? matrix4})
可以传递3个参数,2个必要的,一个可选的:
没有使用matrix4属性:
dart
复制代码
Path path = Path()..moveTo(100, 100); path.lineTo(210, 240); path.lineTo(80, 380); path.addPath(path, const Offset(120, 120)); canvas.drawPath(path, paint);
使用了matrix4属性:
dart
复制代码
Path path = Path()..moveTo(100, 100); path.lineTo(210, 240); path.lineTo(80, 380); // 变形(倾斜)路径 path.addPath(path, const Offset(120, 120), matrix4: Matrix4.skew(.1, .1).storage); canvas.drawPath(path, paint);
效果和path.addPath一样,属性也一样,只是该方法会将这两条线段连接起来:
dart
复制代码
Path path = Path()..moveTo(100, 100); path.lineTo(210, 240); path.lineTo(80, 380); path.extendWithPath(path, const Offset(120, 120), matrix4: Matrix4.skew(.2, .4).storage); canvas.drawPath(path, paint);
添加一条新路径
addPolygon(List points, bool close)
需要传递2个参数:
dart
复制代码
path.moveTo(size.width / 2, 200); path.lineTo(200, 380); path.lineTo(80, 460); List
绘制圆弧路径
arcTo( Rect rect, double startAngle, double sweepAngle, bool forceMoveTo, )
需要传递4个参数:
dart
复制代码
path.moveTo(size.width / 2, 200); path.lineTo(80, 460); Rect rect = Rect.fromPoints(const Offset(80, 340), const Offset(280, 420)); // forceMoveTo为true path.arcTo(rect, 0, 5, true); // forceMoveTo为false path.arcTo(rect, 0, 5, false); canvas.drawPath(path, paint);
绘制一个两点之间线段距离的直径圆弧
arcToPoint(Offset arcEnd, {Radius radius = Radius.zero, double rotation = 0.0, bool largeArc = false, bool clockwise = true})
可以传递5个参数,1个必要的,4个可选的:
dart
复制代码
path.moveTo(100, 200); // p0 path.arcToPoint( const Offset(320, 500), radius: const Radius.circular(.5), rotation: 2, argeArc: true, clockwise: false, ); // p1 path.arcToPoint( onst Offset(160, 250), adius: const Radius.circular(1), otation: 0, argeArc: true, lockwise: false, ); // p2 path.arcToPoint( const Offset(240, 375), radius: const Radius.circular(0), rotation: 5, largeArc: false, clockwise: true, ); canvas.drawPath(path, paint);
效果和path.arcToPoint一样,只是起始点为前一个点
绘制圆锥路径
conicTo(double x1, double y1, double x2, double y2, double w)
需要传递5个参数:
dart
复制代码
path.moveTo(size.width / 2, 200); // 权重=0 path.conicTo(80, 280, 300, 380, 0); // 权重=1 path.conicTo(80, 280, 300, 380, 1); // 权重=2 path.conicTo(80, 280, 300, 380, 2); canvas.drawPath(path, paint);
效果和path.conicTo一样,只是起始点为前一个点
使用控制点 (x1,y1) 添加一个从当前点弯曲到给定点 (x2,y2) 的二次贝塞尔曲线段
quadraticBezierTo( double x1, double y1, double x2, double y2)
需要传递4个参数:
dart
复制代码
path.moveTo(20, 200); path.quadraticBezierTo(200, 80, size.width - 20, size.width); canvas.drawPath(path, paint);
其中p0代表起始点位置(path.moveTo(20, 200)),p1的坐标是**(x1, y1),p2的坐标是(x2, y2)**
效果和path.quadraticBezierTo一样,只是起始点为前一个点
使用控制点 (x1,y1) 和 (x2,y2) 添加从当前点弯曲到给定点 (x3,y3) 的三次贝塞尔曲线段
cubicTo( double x1, double y1, double x2, double y2, double x3, double y3)
需要传递6个参数:
dart
复制代码
path.moveTo(100, 200); path.cubicTo(120, 120, 240, 360, 310, 360); canvas.drawPath(path, paint);
其中p1代表p0点控制线的右边坐标,p2代表p3点控制线的左边坐标
效果和path.cubicTo一样,只是起始点为前一个点
复制线段,并对其路径进行变形。transform(Float64List matrix4)
需要传递一个Float64List对象:
绘制第一条线段:
dart
复制代码
Paint paint = Paint() ..style = PaintingStyle.stroke ..strokeWidth = 8 ..color = Colors.red; Path path = Path(); path.moveTo(80, 100); path.lineTo(140, 200); path.lineTo(320, 280); path.lineTo(100, 400); canvas.drawPath(path, paint);
绘制第二条线段:
dart
复制代码
Paint paint1 = Paint() ..style = PaintingStyle.stroke ..strokeWidth = 8 ..color = Colors.blue; Path path1 = path.transform(Matrix4.skew(.1, .4).storage); canvas.drawPath(path1, paint1);
获取路径的边界矩形
dart
复制代码
path.moveTo(50, 200); path.lineTo(300, 280); // path.getBounds()的结果为Rect.fromLTRB(50.0, 200.0, 300.0, 280.0) print(path.getBounds()); canvas.drawPath(path, paint);
功能和path.add一样,只不过不会自动绘制一份路径,会把路径复制一份然后赋值给其他路径。
第一条路径:
dart
复制代码
Paint paint = Paint() ..style = PaintingStyle.stroke ..strokeWidth = 8 ..color = Colors.red; Path path = Path(); path.moveTo(size.width / 2, 200); path.lineTo(80, 450); path.lineTo(size.width - 80, 450); path.close(); canvas.drawPath(path, paint);
复制第一条路径,并偏移:
dart
复制代码
Paint paint1 = Paint() ..style = PaintingStyle.stroke ..strokeWidth = 8 ..color = Colors.blue; Path path1 = path.shift(const Offset(50, 50)); canvas.drawPath(path1, paint1);
测试给定点是否在路径内。也就是说,如果路径与Canvas.clipPath一起使用,该点是否位于路径的可见部分。
dart
复制代码
Offset point1 = const Offset(200, 320); print(path.contains(point1)); Offset point2 = const Offset(200, 520); print(path.contains(point2));
如果该点在路径内,就返回 true,否则返回 false。
path.computeMetrics可以获取路径的详细信息。
computeMetrics({bool forceClosed = false})
有一个可选参数:
path.close();
,该方法获取的结果isClose将会为false。设置该值为true,isClose将会为true我们先绘制一条普通路径:
dart
复制代码
Paint paint = Paint() ..style = PaintingStyle.stroke ..strokeWidth = 8 ..color = Colors.red; Path path = Path(); path.moveTo(size.width / 2, 200); path.lineTo(80, 450); path.lineTo(size.width - 80, 450); path.close();
如果直接对以上绘制的路径使用path.computeMetrics
,会返回一个PathMetrics
对象:
dart
复制代码
PathMetrics pathMetrics = path.computeMetrics();
一般我们需要用到的是PathMetric
对象,获取该对象一共有以下几种方法:
dart
复制代码
// 如果只有一个PathMetric对象推荐使用该方法 PathMetric pathMetric = pathMetrics.single; // 如果有很多个PathMetric对象使用以下任意方法 PathMetric pathMetric = pathMetrics.elementAt(0); PathMetric pathMetric = pathMetrics.first; PathMetric pathMetric = pathMetrics.last;
获取到PathMetric
对象后,我们就可以沿着这条路径绘制一条新的路径,使用extractPath方法。
该方法可以传递3个参数:
double start
:给定线段开始的距离double end
:给定线段结束的距离bool startWithMoveTo
:是否以 moveTo 点开始绘制线段dart
复制代码
Path path1 = pathMetric.extractPath(50, 400, startWithMoveTo: true);
dart
复制代码
Path path1 = pathMetric.extractPath(50, 400, startWithMoveTo: false);
关于computeMetrics的方法和属性还有很多没讲到,等以后有时间了再慢慢研究。
作者:菠萝橙子丶
链接:https://juejin.cn/post/7083304661645541390
来源:稀土掘金
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。