Flutter---CustomPaint

抽象概念

复制代码
想象你要画一幅画

画布(Canvas) = 一张白纸
画笔(Paint) = 颜料和画笔
画家(CustomPaint) = 你本人

简单比喻

Dart 复制代码
CustomPaint(
    painter:你的画笔工具  //画家使用技巧
    size:画布大小        //纸张尺寸
)

核心三要素

Canvas + Paint + CustomPainter

一.简单案例入门

效果图

代码实例

Dart 复制代码
import 'dart:async';
import 'dart:math';
import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';


class HomePage extends StatefulWidget {
  const HomePage({super.key});

  @override
  State<StatefulWidget> createState() => _HomePageState();
}

class _HomePageState extends State<HomePage> with SingleTickerProviderStateMixin {


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,

      body: Center(
       child: CustomPaint(
         size: Size(200, 200), //画布大小
         painter: CirclePainter(),
       ),
      )
    );
  }
  
}


class CirclePainter extends CustomPainter{
  @override
  void paint(Canvas canvas, Size size) {
    //1.创建画笔
    final paint = Paint()
        ..color = Colors.blue //颜色
      ..style = PaintingStyle.stroke //填充样式 ,fill就是填满,stroke是描边
      ..strokeWidth = 5; //边框宽度(如果使用描边)

    //2.计算圆心位置(画布中心)
    final center = Offset(size.width/2, size.height/2);
    final radius = 50.0;

    //3.绘制圆形
    canvas.drawCircle(center, radius, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;

}

二.绘制简单的图形集合

效果图

代码实例

Dart 复制代码
body: CustomPaint(
        size: Size(400, 400), //画布大小
        painter: BasicShapesPainter(),
      ),

class BasicShapesPainter extends CustomPainter{
  @override
  void paint(Canvas canvas, Size size) {
    //画笔1:红色实心
    final redPaint = Paint()
      ..color = Colors.red //颜色
      ..style = PaintingStyle.fill; //填充样式 ,fill就是填满,stroke是描边

    //画笔2:蓝色描边
    final bluePaint = Paint()
      ..color = Colors.blue
      ..style = PaintingStyle.stroke
      ..strokeWidth = 3;

    //1.绘制矩形
    canvas.drawRect(
      Rect.fromLTRB(50, 50, 150, 150),//左上右下坐标,左和右是用x轴左边,上和下是用y轴坐标,屏幕左上角为圆点(0,0)
      redPaint,
    );

    //2.绘制圆角矩形
    canvas.drawRRect(
      RRect.fromRectAndRadius(
        Rect.fromLTRB(200, 50, 300, 150),
        Radius.circular(20),
      ),
      bluePaint
    );

    //3.绘制直线
    canvas.drawLine(
      Offset(50, 200),//起点
      Offset(250, 200),//终点
      bluePaint
    );
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;

}

Canvas坐标系

坐标系特点

Dart 复制代码
原点 (0,0):在屏幕左上角

X 轴:向右为正方向

Y 轴:向下为正方向(这与数学坐标系不同!)

例子

Dart 复制代码
Rect.fromLTRB(left, top, right, bottom)


表示
left: 矩形左边缘的 X 坐标 = 50

top: 矩形上边缘的 Y 坐标 = 50

right: 矩形右边缘的 X 坐标 = 150

bottom: 矩形下边缘的 Y 坐标 = 150

三.Paint的主要属性

Dart 复制代码
Paint paint = Paint()
  ..color = Colors.blue              // 颜色
  ..style = PaintingStyle.fill       // 填充样式:fill填充 / stroke描边
  ..strokeWidth = 2.0               // 描边宽度
  ..strokeCap = StrokeCap.round     // 线帽样式:round圆角 / butt直角 / square方头
  ..strokeJoin = StrokeJoin.round   // 拐角样式:round圆角 / miter尖角 / bevel斜角
  ..blendMode = BlendMode.srcOver   // 混合模式
  ..isAntiAlias = true              // 抗锯齿
  ..filterQuality = FilterQuality.high // 过滤质量
  ..shader = gradient;              // 渐变着色器

实现渐变案例

效果图

代码实例

Dart 复制代码
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      backgroundColor: Colors.white,

      body: CustomPaint(
        size: Size(200, 200), //画布大小
        painter: GradientPainter(),
      ),
    );
  }

}


class GradientPainter extends CustomPainter{
  @override
  void paint(Canvas canvas, Size size) {

    //创建线性渐变
    final gradient = LinearGradient(
      colors: [Colors.red,Colors.orange,Colors.yellow],
      stops:[0.0,0.5,1.0]
    );

    final paint = Paint()
      ..shader = gradient.createShader(
        Rect.fromLTWH(0, 0, size.width, size.height)
      );

    canvas.drawRect(
      Rect.fromLTWH(0, 0, size.width, size.height),
      paint
    );
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;

}

四.Path路径绘制

示例1:绘制简单形状

效果图

代码实例

Dart 复制代码
class GradientPainter extends CustomPainter{
  @override
  void paint(Canvas canvas, Size size) {

    final paint = Paint()
        ..color = Colors.purple
        ..style = PaintingStyle.stroke
        ..strokeWidth = 4;

    //创建路径
    final path = Path();

    //移动到起点(不划线)
    path.moveTo(50, 50);

    //画直线
    path.lineTo(200, 50);

    //画二次贝塞尔曲线
    path.quadraticBezierTo(250, 100, 200, 150);

    //画三次贝塞尔曲线
    path.cubicTo(150, 200, 100, 100, 50, 150);

    //闭合路径(连接到起点)
    path.close();

    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;

}

示例2:绘制复杂形状

效果图

代码实例

Dart 复制代码
class HeartShapePainter extends CustomPainter{
  @override
  void paint(Canvas canvas, Size size) {

    final paint = Paint()
        ..color = Colors.purple
        ..style = PaintingStyle.fill;

    //创建路径
    final path = Path();

    final centerX = size.width / 2;
    final centerY = size.height / 2;

    //移动到起点(不划线)
    path.moveTo(centerX, centerY);

    //绘制心形
    path.cubicTo(
      centerX + 50, centerY - 40,
      centerX + 90, centerY - 20,
      centerX, centerY + 60,
    );
    path.cubicTo(
      centerX - 90, centerY - 20,
      centerX - 50, centerY - 40,
      centerX, centerY,
    );
    

    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;

}

示例3:绘制平行四边形

效果图

代码实例

Dart 复制代码
class ShapePainter extends CustomPainter{
  @override
  void paint(Canvas canvas, Size size) {

    final paint = Paint()
        ..color = Colors.green
        ..style = PaintingStyle.fill;

    //创建路径
    final path = Path();

    //平行四边形倾斜角度
    final skew = 30.0;

    //4个顶点坐标
    final p1 = Offset(skew, 0);                 // 左上
    final p2 = Offset(size.width, 0);          // 右上
    final p3 = Offset(size.width - skew, size.height); // 右下
    final p4 = Offset(0, size.height);         // 左下


    // 连接点形成平行四边形
    path.moveTo(p1.dx, p1.dy);
    path.lineTo(p2.dx, p2.dy);
    path.lineTo(p3.dx, p3.dy);
    path.lineTo(p4.dx, p4.dy);
    path.close(); // 闭合路径


    canvas.drawPath(path, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) => false;

}
相关推荐
火柴就是我8 小时前
学习一些常用的混合模式之BlendMode.srcIn
flutter
菜的不敢吱声8 小时前
swift学习第2,3天
python·学习·swift
恋猫de小郭8 小时前
罗技鼠标因为服务器证书过期无法使用?我是如何解决 SSL 证书问题
android·前端·flutter
l04090442229 小时前
想学习VLN相关的知识,并亲手搭建一套系统,该如何入手?
学习
山土成旧客9 小时前
【Python学习打卡-Day36】实战重构:用PyTorch神经网络升级信贷预测项目
python·学习·重构
麻雀无能为力9 小时前
VAE(变分自编码器 Variational Auto-Encoder)学习笔记
笔记·学习
程序员老刘9 小时前
ArkUI-X 6.0 跨平台框架能否取代 Flutter?
flutter·客户端·arkui
挽天java9 小时前
X86汇编语言期末复习
学习
北岛寒沫9 小时前
北京大学国家发展研究院 经济学原理课程笔记(第十九课 长期经济增长)
经验分享·笔记·学习