• flutter 绘画


    效果:

     

     实现:

    import 'dart:math';
    import 'package:flutter/cupertino.dart';
    import 'package:flutter/material.dart';
    import 'package:flutter/rendering.dart';
    
    class CustomPaintPainterPage extends StatefulWidget {
      const CustomPaintPainterPage({Key? key}) : super(key: key);
    
      @override
      State<CustomPaintPainterPage> createState() => _CustomPaintPainterPageState();
    }
    
    class _CustomPaintPainterPageState extends State<CustomPaintPainterPage> {
      @override
      Widget build(BuildContext context) {
        return SingleChildScrollView(
          child: Column(
            crossAxisAlignment: CrossAxisAlignment.start,
            children: [
              const Text('基础理解', style: TextStyle(color: Colors.red)),
              const Text("    Paint:在画布上绘制时要使用的样式的描述(可描述为画笔)"),
              const Text("    Canvas:用于记录图形操作的界面(可描述为画布)"),
              const Text(
                  "    Path:可以使用Canvas.drawPath在画布上绘制路径。并可用于使用Canvas.clipPath创建剪辑区域"),
              const SizedBox(height: 20),
              const Text("在flutter中并不是直接使用Paint、Canvas,而是使用进一步封装的widget,如下"),
              const Text(
                  '官方https://api.flutter.dev/flutter/widgets/CustomPaint-class.html'),
              const Text('CustomPaint:', style: TextStyle(color: Colors.red)),
              const Text('    提供在绘制阶段绘制的画布,并利用CustomPainter来运行绘制指令的组件'),
              const Text('    它通常会将painter和child内嵌在其构造函数内:'),
              const Text('     painter是CustomPainter类的实例'),
              const Text('CustomPainter:', style: TextStyle(color: Colors.red)),
              const Text(
                  '    CustomPaint(在widgets库中)和RenderCustomPaint(在渲染库中)使用的接口'),
              const Text('    画布绘制发生的地方'),
              const Text('    CustomPainter基类化,需要重写两个功能paint和shouldRepaint:'),
              const Text('    CustomPainter基类化,需要重写两个功能paint和shouldRepaint:'),
              const Text(
                  '    paint方法是用于绘制的,它有两个参数Canvas和Size,所有的绘制指令应在指定大小的范围中发生;shouldRepaint它控制painter重绘的时间'),
              const SizedBox(
                height: 50,
              ),
              CustomPaint(
                foregroundPainter: MyPainter(),
                child: Container(
                  color: Colors.blue,
                   600,
                  height: 200,
                ),
              ),
              const SizedBox(
                height: 50,
              ),
              CustomPaint(
                foregroundPainter: SmilePainter(),
                child: Container(
                  color: Colors.blue,
                   600,
                  height: 200,
                ),
              ),
              const SizedBox(
                height: 50,
              ),
              CustomPaint(
                foregroundPainter: Sky(),
                child: Container(
                  color: Colors.white,
                   600,
                  height: 200,
                ),
              ),
              const SizedBox(
                height: 50,
              ),
              CustomPaint(
                painter: Sky(),
                child: const Center(
                  child: Text(
                    'Once upon a time...',
                    style: TextStyle(
                      fontSize: 40.0,
                      fontWeight: FontWeight.w900,
                      color: Color(0xFFFFFFFF),
                    ),
                  ),
                ),
              ),
              const SizedBox(
                height: 50,
              ),
              CustomPaint(
                foregroundPainter: Pentagram(Colors.black),
                child: Container(
                  color: Colors.blue,
                   200,
                  height: 200,
                ),
              ),
            ],
          ),
        );
      }
    }
    
    class Pentagram extends CustomPainter {
      Pentagram(this.color);
      //画笔的颜色
      final Color color;
    
      @override
      void paint(Canvas canvas, Size size) {
        Offset getOffsetPosition(int degreen, double radius) {
          //角度转成弧度
          var radian = degreen * pi / 180;
          var dx = sin(radian) * radius;
          var dy = cos(radian) * radius;
          return Offset(dx + radius, dy + radius);
        }
    
        final paint = Paint()
          ..color = Colors.black
          ..style = PaintingStyle.fill;
    
        var initDegreen = 180;
        double radius = 100;
        // 连接五角星的五个顶点,360/5,每个是72度
        final path = Path();
        var posOne = getOffsetPosition(initDegreen, radius);
        var posTwo = getOffsetPosition(72 + initDegreen, radius);
        var posThree = getOffsetPosition(144 + initDegreen, radius);
        var posfour = getOffsetPosition(216 + initDegreen, radius);
        var posFive = getOffsetPosition(288 + initDegreen, radius);
        path.moveTo(posOne.dx, posOne.dy);
        path.lineTo(posfour.dx, posfour.dy);
        path.lineTo(posTwo.dx, posTwo.dy);
        path.lineTo(posFive.dx, posFive.dy);
        path.lineTo(posThree.dx, posThree.dy);
        //最后用close的方式把path封闭起来
        path.close();
        canvas.drawPath(path, paint);
      }
    
      @override
      bool shouldRepaint(covariant CustomPainter oldDelegate) {
        // TODO: implement shouldRepaint
        return false;
      }
    }
    
    class SmilePainter extends CustomPainter {
      @override
      void paint(Canvas canvas, Size size) {
        const radius = 100.0;
        final center = Offset(size.width / 2.0, size.height / 2.0);
        final paint = Paint()..color = Colors.yellow;
        canvas.drawCircle(center, radius, paint);
        final smilePaint = Paint()
          ..style = PaintingStyle.stroke
          ..strokeWidth = 10;
        canvas.drawArc(Rect.fromCircle(center: center, radius: radius / 2), 0, pi,
            false, smilePaint);
        canvas.drawCircle(
            Offset(center.dx - radius / 2.0, center.dy - radius / 2.0),
            10,
            Paint());
        canvas.drawCircle(
            Offset(center.dx + radius / 2.0, center.dy - radius / 2.0),
            10,
            Paint());
      }
    
      @override
      bool shouldRepaint(covariant CustomPainter oldDelegate) {
        // TODO: implement shouldRepaint
        return false;
      }
    }
    
    class Sky extends CustomPainter {
      @override
      void paint(Canvas canvas, Size size) {
        final Rect rect = Offset.zero & size;
        const RadialGradient gradient = RadialGradient(
          center: Alignment(0.7, -0.6),
          radius: 0.2,
          colors: <Color>[Color(0xFFFFFF00), Color(0xFF0099FF)],
          stops: <double>[0.4, 1.0],
        );
        canvas.drawRect(
          rect,
          Paint()..shader = gradient.createShader(rect),
        );
      }
    
      @override
      SemanticsBuilderCallback get semanticsBuilder {
        return (Size size) {
          // Annotate a rectangle containing the picture of the sun
          // with the label "Sun". When text to speech feature is enabled on the
          // device, a user will be able to locate the sun on this picture by
          // touch.
          Rect rect = Offset.zero & size;
          final double width = size.shortestSide * 0.4;
          rect = const Alignment(0.8, -0.9).inscribe(Size(width, width), rect);
          return <CustomPainterSemantics>[
            CustomPainterSemantics(
              rect: rect,
              properties: const SemanticsProperties(
                label: 'Sun',
                textDirection: TextDirection.rtl,
              ),
            ),
          ];
        };
      }
    
      @override
      bool shouldRepaint(Sky oldDelegate) => false;
      @override
      bool shouldRebuildSemantics(Sky oldDelegate) => false;
    }
    
    class MyPainter extends CustomPainter {
      @override
      void paint(Canvas canvas, Size size) {
        Paint onePaint = Paint()
          ..style = PaintingStyle.fill // 是否填充
          ..color = Colors.red
          ..strokeWidth = 3;
        Paint twoPaint = Paint()
          ..style = PaintingStyle.stroke // 是否填充
          ..color = Colors.white
          ..strokeWidth = 3;
        // canvas.drawPaint(newPaint);
        canvas.drawCircle(const Offset(75, 95), 50, onePaint);
        canvas.drawLine(const Offset(70, 30), const Offset(170, 30), onePaint);
        canvas.drawRect(
            Rect.fromPoints(const Offset(140, 80), const Offset(190, 60)),
            onePaint);
        canvas.drawCircle(const Offset(275, 95), 50, twoPaint);
        canvas.drawLine(const Offset(270, 30), const Offset(370, 30), twoPaint);
        canvas.drawRect(
            Rect.fromPoints(const Offset(340, 80), const Offset(390, 60)),
            twoPaint);
      }
    
      @override
      bool shouldRepaint(covariant CustomPainter oldDelegate) {
        // TODO: implement shouldRepaint
        return false;
      }
    }
  • 相关阅读:
    @ControllerAdvice 全局异常处理
    SpringBoot 单文件和多文件上传
    Springboot application 本地HTTPS配置
    不使用spring-boot-starter-parent进行依赖的版本管理
    构造函数和函数式接口
    函数式接口和Lambda表达式
    使用FunctionalInterface提供工厂方法
    Future 和 CompletableFuture 异步任务 in Java
    单例
    使用私有仓库(Docker Registry 2.0)管理镜像
  • 原文地址:https://www.cnblogs.com/lulushen/p/16313336.html
Copyright © 2020-2023  润新知