Flutter CustomPaint,canvas绘制组件

前言:

        Flutter是一个UI框架,一切皆Widget,Flutter可以说和Android是无缝对接,毕竟都是出自Google,Material风格更是轻车熟路,对Android同学来说,上手较快.本文要讲的Canvas也和Android中Canvas也是极其相似,一脉相承.Canvas一般可以用来绘制比较难以实现的特殊图形,控件等,比如一些多边形,弧形等等吧.Canvas就是画布,内部封装了用于绘制绘制基本图形的接口,比如矩形,圆形,点,线等.
        Flutter中为我们提供了封装好的组件CustomPaint Widget,这个组件与画笔Paint Widget组合使用就可以绘制出需要的图形.

Flutter绘制的基本步骤:

1. 创建继承于基类的绘制类

///
/// @ClassName FlutterPainter
/// @Description 绘制类
/// @Author waitwalker
/// @Date 2020-03-07
///
class FlutterPainter extends CustomPainter {
  
}

2. 在绘制类中重写paint()和shouldRepaint()方法

///
/// @ClassName FlutterPainter
/// @Description 绘制类
/// @Author waitwalker
/// @Date 2020-03-07
///
class FlutterPainter extends CustomPainter {

  @override
  void paint(Canvas canvas, Size size) {
    // TODO: implement paint
  }
  
  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    // TODO: implement shouldRepaint
    return null;
  }
}

3. 初始化画笔Paint&调用Canvas绘制图形

///
/// @ClassName FlutterPainter
/// @Description 绘制类
/// @Author waitwalker
/// @Date 2020-03-07
///
class FlutterPainter extends CustomPainter {

  @override
  void paint(Canvas canvas, Size size) {
    /// 初始化画笔
    var paint = Paint()
        ..strokeWidth = 25.0
        ..color = Colors.red;
    
    /// 通过canvas画一条直线
    /// 这里可以根据需要绘制圆形,矩形等等
    canvas.drawLine(Offset(95, 0), Offset(95, 300), paint);
  }

  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    return true;
  }
}

4. 初始化CustomPaint添加成员变量绘制类,并把CustomPaint添加到Widget树中

class _HomeState extends State<HomePage> {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: CustomPaint(
          foregroundPainter: FlutterPainter(),
          child: Container(
            width: 200,
            height: 200,
            color: Color(0x5a00C800),
          ),
        ),
      ),
    );
  }

///
/// @ClassName FlutterPainter
/// @Description 绘制类
/// @Author waitwalker
/// @Date 2020-03-07
///
class FlutterPainter extends CustomPainter {

  @override
  void paint(Canvas canvas, Size size) {
    // TODO: implement paint
  }
  
  @override
  bool shouldRepaint(CustomPainter oldDelegate) {
    // TODO: implement shouldRepaint
    return null;
  }
}
}

CustomPainter 说明:

CustomPainter是真实绘制的基础类,需要绘制的图形和画笔都是在此类中实现,一般会自定义一个类继承此基类,然后重写两个方法如下:

1.1 paint 方法

这个方法就是实现具体绘制的方法

@override
void paint(Canvas canvas, Size size) {
  // TODO: implement paint
}

1.2 shouldRepaint 方法

这个方法控制的是是否需要重绘

@override
bool shouldRepaint(CustomPainter oldDelegate) {
  // TODO: implement shouldRepaint
  return null;
}

CustomPaint 绘制组件

CustomPaint可以理解为绘制的封装类,其内部成员变量就包含CustomPainter,其构造函数:

const CustomPaint({
  Key key,
  this.painter,
  this.foregroundPainter,
  this.size = Size.zero,
  this.isComplex = false,
  this.willChange = false,
  Widget child,
})
图片[1]-Flutter CustomPaint,canvas绘制组件-IT网络技术分享

1.painter: 自定义绘制的基础类绘制效果会显示在child的下面,效果如上:

图片[2]-Flutter CustomPaint,canvas绘制组件-IT网络技术分享

2.foregroundPainter:自定义绘制的基础类绘制效果会显示在child的上面,效果如上:

3.child:子控件,也就是上图中的绿色区域.
4.size:绘制区域大小,其取决于child.
(1)如果child == null,则绘制区域为size大小;
(2)如果child != null,则绘制区域为child大小;
(3)如果想child != null && 指定size大小,可以用SizeBox包裹一下CustomPaint;
5.isComplex:是否复杂绘制,默认false,如果true,则会开启缓存,避免一些不必要的绘制提高性能.
6.willChange:这个和isComplex一起使用,默认false,如果isComplex == true,willChange表示绘制下一帧是否会改变


Canvas 的方法

Canvas 的操作主要有两类:

  • 针对 Canvas 的变换操作,如平移、旋转、缩放、图层等
  • 绘制基础图形的操作,如线段、路径、图片、几何图形等

绘制相关操作:

  • drawArc(Rect rect,double startAngle, double sweepAngle, bool useCenter, Paint paint)在给定的矩形中画一个弧线。它从椭圆周围的startAngle弧度开始,直至椭圆周围的startAngle+sweepAngle弧度,零弧度是椭圆右侧与矩形中心相交的水平线相交的点,正角绕椭圆顺时针走。如果useCenter为真,弧线就会闭合回到中心,形成一个圆扇形。否则,弧线不闭合,形成一个圆段。
参数类型说明
rectRect圆弧所在椭圆的外接矩形
startAngledouble起始位置的弧度。弧度制
sweepAngledouble设置圆弧扫过多少弧度。弧度制
useCenterbool表示是否链接到圆弧所在椭圆的中心
paintPaint画笔
  • drawAtlas(Image atlas, List<RSTransform> transforms, List<Rect> rects, List<Color> colors, BlendMode blendMode, Rect cullRect, Paint paint)在画布上绘制部分图像。当你只想在画布上绘制图像的一部分时(例如使用精灵或缩放时),此方法可以进行优化。 比直接使用剪辑或遮罩更有效。
  • drawCircle(Offset c, double radius, Paint paint)绘制一个以第一个参数给出的点为中心的圆,其半径由第二个参数给出,第三个参数给出Paint。圆圈是被填充还是被描边(或者两者都有)由Paint.style控制。
  • drawColor(Color color, BlendMode blendMode)将给定的Color应用给定的BlendMode绘制到画布上,给定的颜色为源色,背景为目标色。
  • drawDRRect(RRect outer, RRect inner, Paint paint)用给定的Paint绘制一个由两个圆角矩形的差值组成的形状。这个形状是填充还是描边(或者两者都有)由Paint.style控制。
  • drawImage(Image image, Offset p, Paint paint)将给定的Image以给定的Offset的左上角绘制到画布中。使用给定的Paint将图像合成到画布中。
  • drawImageNine(Image image, Rect center, Rect dst, Paint paint)使用给定的 Paint 将给定的 Image 绘制到画布上。使用给定的Paint将给定的Image绘制到画布中。通过绘制两条水平线和两条垂直线将图像分割成九个部分进行绘制,其中中心参数描述了由这四条线相交的四个点形成的矩形。这样就形成了一个3×3的区域网格,中心区域由中心参数描述)。角落中的四个区域是在dst描述的目标矩形的四个角上绘制的,没有缩放。剩下的五个区域是通过拉伸来绘制的,使它们完全覆盖目标矩形,同时保持它们的相对位置。
  • drawImageRect(Image image, Rect src, Rect dst, Paint paint)在 dst 参数给定的轴对齐的矩形中,将 src 参数描述的给定图像的一部分绘制到画布中。
  • drawLine(Offset p1, Offset p2, Paint paint)使用给定的paint在给定的两点之间绘制一条线。 描边该行,此调用将忽略Paint.style的值。
  • drawOval(Rect rect, Paint paint)绘制一个轴对齐的椭圆形,用给定的Paint填充给定的轴对齐的矩形。椭圆是被填充还是被描边(或两者都有)由Paint.style控制。
  • drawPaint(Paint paint)用给定的Paint填充画布。
  • drawParagraph(Paragraph paragraph, Offset offset)将给定Paragraph中的文本在给定Offset处绘制到这个画布中。
  • drawPath(Path path, Paint paint)用给定的 Paint 绘制给定的 Path。这个形状是被填充还是被描边(或者两者都有)由 Paint.style 控制。如果路径被填充,那么它的子路径将被隐式关闭(参见 Path.close)。
  • drawPicture(Picture picture)在画布上绘制给定的图片。要创建图片,请参阅PictureRecorder
  • drawPoints(PointMode pointMode, List points, Paint paint)根据给定的PointMode绘制一个点的序列。
  • drawRawAtlas(Image atlas, Float32List rstTransforms, Float32List rects, Int32List colors, BlendMode blendMode, Rect cullRect, Paint paint)将图像的一部分atlas画在画布上。
  • drawRawPoints(PointMode pointMode, Float32List points, Paint paint)根据给定的PointMode绘制一个点的序列。
  • drawRect(Rect rect, Paint paint)用给定的Paint绘制一个矩形。矩形是被填充还是被描边(或两者都有)由Paint.style控制。
  • drawRRect(RRect rrect, Paint paint)用给定的Paint绘制一个圆角矩形。矩形是被填充还是被描边(或两者都有)由Paint.style控制。
  • drawShadow(Path path, Color color, double elevation, bool transparentOccluder)为Path画出代表给定material标高的阴影。
  • drawVertices(Vertices vertices, BlendMode blendMode, Paint paint)将Vertices的集合绘制到画布上。

变换相关操作:

  • scale(double sx, [double sy])在当前变换中添加一个轴对齐的标尺,在水平方向上按第一个参数缩放,在垂直方向上按第二个参数缩放。
  • skew(double sx, double sy)在当前变换中增加一个轴对齐的倾斜度,第一个参数是以原点为单位顺时针上升的水平倾斜度,第二个参数是以原点为单位顺时针上升的垂直倾斜度。
  • transform(Float64List matrix4)将当前变换乘以指定的4×4变换矩阵,该矩阵指定为以列为主的值列表。
  • translate(double dx, double dy)在当前的变换中添加一个平移,通过第一个参数水平移动坐标空间,通过第二个参数垂直移动坐标空间。
  • rotate(double radians)在当前的变换中加入旋转。参数的单位是顺时针的弧度。
  • getSaveCount()返回保存栈中的条目数,包括初始状态。这意味着如果画布是干净的,则返回1,每次调用savesaveLayer都会使其递增,每次匹配调用restore都会使其递减。
  • restore()弹出当前的保存堆栈(如果有要弹出的内容)。 否则,什么都不做。
  • save()在保存堆栈上保存当前变换和剪辑的副本。
  • saveLayer(Rect bounds, Paint paint)在保存堆栈上保存当前变换和剪辑的副本,然后创建一个新的组,后续调用将成为该组的一部分。当随后打开保存堆栈时,该组将被扁平化为一个图层,并应用给定的paintPaint.colorFilterPaint.blendMode

裁剪相关操作:

  • clipPath(Path path, {bool doAntiAlias: true})将剪辑区域缩小至目前剪辑与给定路径的交点。如果doAntiAlias为true,则剪辑将被消除锯齿。
  • clipRect(Rect rect, {ClipOp clipOp: ClipOp.intersect, bool doAntiAlias: true})缩小剪辑区域至目前剪辑与指定矩形的交点
  • clipRRect(RRect rrect, {bool doAntiAlias: true})将剪辑区域缩小到当前剪辑和给定圆角矩形的交点。


Paint 画笔

Canvas上绘图时要使用的样式的描述。大多数Canvas上的API都会取一个Paint对象来描述该操作要使用的样式。简单说,该类主要是用来设置真正画笔的一些属性。【 Paint是画笔,画笔有多个属性,可以设置颜色,线宽,填充等样式.

属性类型简述
isAntiAliasbool是否开启抗锯齿,开启抗锯齿能够使边缘平滑
colorColor描边或填充形状时使用的颜色。
colorFilterColorFilter绘制形状或合成图层时应用的颜色滤镜。
filterQualityFilterQuality控制应用滤镜(如 maskFilter)或绘制图像(如 Canvas.drawImageRect 或 Canvas.drawImageNine)时的性能与质量权衡。
invertColorsbool绘制时图像的颜色是否反转
maskFilterMaskFilter遮罩滤镜(例如,模糊),在形状被绘制后,但在它被合成到图像之前,应用于它。
imageFilterImageFilter绘制光栅图像时要使用的ImageFilter。例如,如果要使用Canvas.drawImage模糊图像,应用ImageFilter.blur
shaderShader描边或填充形状时要使用的着色器。
strokeCapStrokeCap当样式设置为PaintingStyle.stroke时,要放置在线条末端的边缘风格。如圆角、方形等
strokeJoinStrokeJoin设置两个绘制形状衔接处的风格。如圆角、方形等
strokeWidthdouble当样式设置为PaintingStyle.stroke时,画笔的宽度。宽度以逻辑像素为单位
stylePaintingStyle填充方式。PaintingStyle.fill充满;PaintingStyle.stroke空心
blendModeBlendMode像素混合模式。当画一个shape或者合成图层的时候会生效。

关于BlendMode类型,官方做了详细解释,这里给一篇 中文翻译链接

THE END
喜欢就支持一下吧
点赞8 分享