Flutter Path(一) : Path 与 CustomPainter

Flutter 为咱们提供了许多标准的组件可供咱们在项目中使用,可是咱们也经常须要本身去自定义 View,而自定义 View 最多见也是最基础的就是使用 Path 了。html

接下来正式开始学习 Path。git

1、前期准备

先来看一段代码。github

import 'package:flutter/material.dart';

void main() => runApp(
      MaterialApp(
        home: PathExample(),
      ),
    );

class PathExample extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return CustomPaint(
      painter: PathPainter(),
    );
  }
}

class PathPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()
      ..color = Colors.red
      ..style = PaintingStyle.stroke
      ..strokeWidth = 8.0;

    Path path = Path();
    // TODO: do operations here
    path.close();
    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) => true;
}
复制代码

在上面代码里,咱们主页面是 StatelessWidget 类型的组件,在 build 方法里面返回的是 CustomPaint 这个 Widget,而 CustomPaint 须要使用的 painter 是咱们自定义的 PathPainter 。CustomPaint 这个组件为咱们提供了一个画布 (canvas),咱们可使用咱们自定义的 CustomPainter 在这个画布上把 paint() 这个方法里面指定的内容绘制上去。编程

对于绘制有关的选项,咱们能够经过 Paint 组件来进行设置,包括颜色、样式、画笔粗细等。canvas

Paint paint = Paint()
   ..color = Colors.blueAccent             //画笔颜色
   ..strokeCap = StrokeCap.round           //画笔笔触类型
   ..isAntiAlias = true                    //是否启动抗锯齿
   ..blendMode = BlendMode.exclusion       //颜色混合模式
   ..style = PaintingStyle.fill            //绘画风格,默认为填充
   ..colorFilter = ColorFilter.mode(Colors.blueAccent,
       BlendMode.exclusion)                //颜色渲染模式
   ..maskFilter = MaskFilter.blur(BlurStyle.inner, 3.0) //模糊遮罩效果
           ..filterQuality = FilterQuality.high //颜色渲染模式的质量
   ..strokeWidth = 5.0;                        //画笔的宽度
复制代码

接下来咱们就能够定义一个 Path 对象来决定画什么了。 Path 这个对象实际上是一些列须要绘制的元素的集合,这些元素在绘制的时候都是根据一个起始点来绘制的(默认的 Path 的起始点是 (0,0) )。api

最后须要使用 canvas 的 drawPath 方法来绘制 path ,这个方法须要两个参数一个是 path 另外一个是 paint 。bash

使用 Path 进行绘图的基本流程差很少就是这些。对于手机上的坐标系统,以下所示,左上角为坐标原点。微信

2、moveTo

moveTo 方法就把绘制的七点移动到指定的位置。less

@override
 void paint(Canvas canvas, Size size) {
   Paint paint = Paint()
     ..color = Colors.red
     ..style = PaintingStyle.stroke
     ..strokeWidth = 8.0;

   Path path = Path();
   // 将起点移动到屏幕中心
   path.moveTo(size.width / 2, size.height / 2);
   canvas.drawPath(path, paint);
 }

复制代码

3、lineTo

lineTo 方法就是从起点绘制一条直线到 lineTo 里面指定的一个点。ide

@override
 void paint(Canvas canvas, Size size) {
   Paint paint = Paint()
     ..color = Colors.red
     ..style = PaintingStyle.stroke
     ..strokeWidth = 8.0;

   Path path = Path();
   // 从左上角起点到右下角终点
   path.lineTo(size.width, size.height);
   canvas.drawPath(path, paint);
 }
复制代码

4、quadraticBezierTo

quadraticBezierTo 是绘制二阶贝塞尔曲线的。

从上图能够看到,绘制贝塞尔曲线须要三个点,一个起点,一个控制点,一个终点。

@override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()
      ..color = Colors.red
      ..style = PaintingStyle.stroke
      ..strokeWidth = 8.0;

    Path path = Path();
    path.moveTo(0, size.height / 2);
    path.quadraticBezierTo(size.width / 2, size.height, size.width, size.height / 2);
    canvas.drawPath(path, paint);
  }
复制代码

5、cubicTo

cubicTo 是绘制三阶贝塞尔曲线的。

三阶贝塞尔须要两个控制点。

@override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()
      ..color = Colors.red
      ..style = PaintingStyle.stroke
      ..strokeWidth = 8.0;
    
    Path path = Path();
    path.cubicTo(size.width / 4, 3 * size.height / 4, 3 * size.width / 4, size.height / 4, size.width, size.height);
    canvas.drawPath(path, paint);
  }
复制代码

6、conicTo

conicTo 方法也是绘制二次曲线的,和 quadraticBeizerTo 方法相似,可是这个方法主要是受到 weight 参数的控制。 当 weight 大于 1 时,绘制的是双曲线,等于 1 时,绘制的是抛物线,小于1 时,绘制的是椭圆。

@override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()
      ..color = Colors.red
      ..style = PaintingStyle.stroke
      ..strokeWidth = 8.0;

    Path path = Path();
    path.conicTo(size.width / 4, 3 * size.height / 4, size.width, size.height, 20);
    canvas.drawPath(path, paint);
  }
复制代码

7、arcTo

arcTo 方法是绘制弧线的,方法原型以下:

void arcTo(Rect rect, double startAngle, double sweepAngle, bool forceMoveTo)
复制代码

须要四个参数:

  • rect: 圆弧所在矩形
  • startAngle : 开始弧度
  • sweepAngle : 须要绘制的弧度大小
  • forceMoveTo : 若是“forceMoveTo”参数为false,则添加一条直线段和一条弧段。 若是“forceMoveTo”参数为true,则启动一个新的子路径,其中包含一个弧段。
@override
  void paint(Canvas canvas, Size size) {
    Paint paint = Paint()
      ..color = Colors.red
      ..style = PaintingStyle.stroke
      ..strokeWidth = 8.0;

    // Method to convert degree to radians
    num degToRad(num deg) => deg * (Math.pi / 180.0);

    Path path = Path();
    path.arcTo(Rect.fromLTWH(size.width / 2, size.height / 2, size.width / 4, size.height / 4), degToRad(0), degToRad(90), true);
    canvas.drawPath(path, paint);
  }
复制代码

8、addRect

绘制矩形。

@override
 void paint(Canvas canvas, Size size) {
   Paint paint = Paint()
     ..color = Colors.red
     ..style = PaintingStyle.stroke
     ..strokeWidth = 8.0;

   Path path = Path();
   // Adds a rectangle
   path.addRect(Rect.fromLTWH(size.width / 2, size.height / 2, size.width / 4, size.height / 4));
   canvas.drawPath(path, paint);
 }
复制代码

9、addOval

绘制椭圆。

@override
 void paint(Canvas canvas, Size size) {
   Paint paint = Paint()
     ..color = Colors.red
     ..style = PaintingStyle.stroke
     ..strokeWidth = 8.0;

   Path path = Path();
   // Adds an oval
   path.addOval(Rect.fromLTWH(size.width / 2, size.height / 2, size.width / 4, size.height / 4));
   canvas.drawPath(path, paint);
 }
复制代码

10、addArc

绘制弧线相似与 arcTo

@override
 void paint(Canvas canvas, Size size) {
   Paint paint = Paint()
     ..color = Colors.red
     ..style = PaintingStyle.stroke
     ..strokeWidth = 8.0;

   // Method to convert degree to radians
   num degToRad(num deg) => deg * (Math.pi / 180.0);

   Path path = Path();
   // Adds a quarter arc
   path.addArc(Rect.fromLTWH(0, 0, size.width, size.height), degToRad(180), degToRad(90));
   canvas.drawPath(path, paint);
 }
复制代码

11、addPolygon

绘制多边形。能够指定多边形的顶点,而且最后一个参数是 ture 时,最后一个点和第一个点会链接,多边形闭合, false 时,不会闭合。

@override
 void paint(Canvas canvas, Size size) {
   Paint paint = Paint()
     ..color = Colors.red
     ..style = PaintingStyle.stroke
     ..strokeWidth = 8.0;

   Path path = Path();
   // Adds a polygon from the starting point to quarter point of the screen and lastly
   // it will be in the bottom middle. Close method will draw a line between start and end.
   path.addPolygon([
     Offset.zero,
     Offset(size.width / 4, size.height / 4),
     Offset(size.width / 2, size.height)
   ], false);
   canvas.drawPath(path, paint);
 }
复制代码
  • false

  • true

12、addRRect

绘制圆角矩形,圆角弧度由最后一个参数控制。

@override
 void paint(Canvas canvas, Size size) {
   Paint paint = Paint()
     ..color = Colors.red
     ..style = PaintingStyle.stroke
     ..strokeWidth = 8.0;

   Path path = Path();
   path.addRRect(
     RRect.fromRectAndRadius(Rect.fromLTWH(size.width / 2, size.height / 2, size.width / 4, size.height / 4), Radius.circular(16))
   );
   canvas.drawPath(path, paint);
 }
复制代码

十3、path 实践绘制进度条

class CircleProgressBarPainter extends CustomPainter {
 //背景
 Paint _paintBackground;

 //前景
 Paint _paintForeground;

 var currentValue;

 CircleProgressBarPainter(this.currentValue) {

   _paintBackground = Paint()
     ..color = Colors.blue
     ..strokeCap = StrokeCap.round
     ..style = PaintingStyle.stroke
     ..strokeWidth = 10.0
     ..isAntiAlias = true;

   _paintForeground = Paint()
     ..color = Colors.red
     ..strokeCap = StrokeCap.round
     ..style = PaintingStyle.stroke
     ..strokeWidth = 10.0
     ..isAntiAlias = true;

 }
 @override
 void paint(Canvas canvas, Size size) {

   //画背景
   canvas.drawCircle(Offset(size.width / 2, size.height / 2), size.width / 2,
       _paintBackground);


   Rect rect = Rect.fromCircle(
     center: Offset(size.width / 2, size.height / 2),
     radius: size.width / 2,
   );

   //画弧形进度
   canvas.drawArc(rect, 0.0, currentValue * Math.pi / 180, false, _paintForeground);
 }



 @override
 bool shouldRepaint(CustomPainter oldDelegate) {
   return false;
 }
}
复制代码

使用

return Container(
     width: width,
     height: height,
     padding: EdgeInsets.all(20),
     child: CustomPaint(

         child: Center(
             child: Text(
                 (progressAnimation.value / 3.6).round().toString(),
             style: TextStyle(fontSize: 24,color: Colors.blue),
             ),
         ),

         painter: CircleProgressBarPainter(progressAnimation.value)

     ),

   );
复制代码

效果:

参考: medium.com/flutter-com…


github


欢迎关注「Flutter 编程开发」微信公众号 。

相关文章
相关标签/搜索