Flutter 关于Canvas和Paint基本练习

247 阅读1分钟

「这是我参与2022首次更文挑战的第12天,活动详情查看:2022首次更文挑战

Flutter 的画布和Android的几乎一致。写了下小练习。记录一下

import 'dart:math';
import 'dart:ui' as ui;

import 'package:flutter/cupertino.dart';
import 'package:flutter/material.dart';

class Paper extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Container(
      color: Colors.white,
      child: CustomPaint(
        painter: PaperPainter(),
      ),
    );
  }
}

class PaperPainter extends CustomPainter {
  @override
  void paint(Canvas canvas, Size size) {
//   canvasCircle(canvas);
//     aboutPaint(canvas);
//    drawStrokeJoin(canvas);
    canvasTranslate(canvas, size);
//  canvasGrid(canvas, size);
    canvasBottomRight(canvas, size);
    drawDot(canvas);
    drawPoint(canvas);
    drawCoordinate(canvas, size);
//    drawRect(canvas);
//    drawRRect(canvas);
//    drawDRRect(canvas);
//    drawFill(canvas);
//    drawArcDetail(canvas);
    drawPaint(canvas, size);
//    drawShadow(canvas);
//    drawPath(canvas);
    clipCanvas(canvas);
  }

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

  ///画圆
  canvasCircle(Canvas canvas) {
    final Paint paint = Paint();
    canvas.drawCircle(
        Offset(180, 180),
        150,
        paint
          ..color = Colors.blue
          ..style = PaintingStyle.stroke
          ..strokeWidth = 50);

    canvas.drawCircle(
        Offset(180 + 360.0, 180),
        150,
        paint
          ..color = Colors.red
          ..style = PaintingStyle.fill
          ..strokeWidth = 50
          ..isAntiAlias = false);
  }

  ///画笔
  ///StrokeCap.butt - 不出头
  //StrokeCap.round - 圆头
  //StrokeCap.square - 方头
  void aboutPaint(Canvas canvas) {
    Paint paint = Paint();
    paint
      ..style = PaintingStyle.stroke
      ..strokeWidth = 20
      ..color = Colors.red;
    canvas.drawLine(
        Offset(50, 50), Offset(50, 150), paint..strokeCap = StrokeCap.butt);
    canvas.drawLine(Offset(50 + 50.0, 50), Offset(50 + 50.0, 150),
        paint..strokeCap = StrokeCap.round);
    canvas.drawLine(Offset(50 + 50.0 * 2, 50), Offset(50 + 50.0 * 2, 150),
        paint..strokeCap = StrokeCap.square);
  }

  ///线接类型
  ///StrokeJoin.bevel - 斜角、
  //StrokeJoin.miter - 锐角、
  //StrokeJoin.round - 圆角
  void drawStrokeJoin(Canvas canvas) {
    Paint paint = Paint();
    Path path = Path();
    paint
      ..style = PaintingStyle.stroke
      ..color = Colors.blue
      ..strokeWidth = 20;
    path.moveTo(50, 50);
    path.lineTo(50, 100);
    path.relativeLineTo(100, -50);
    path.relativeLineTo(0, 100);
//    canvas.drawPath(path, paint..strokeJoin = StrokeJoin.bevel);
//    canvas.drawPath(path, paint..strokeJoin = StrokeJoin.miter);
    canvas.drawPath(path, paint..strokeJoin = StrokeJoin.round);
  }

  ///Canvas 画布变换和状态
  void canvasTranslate(Canvas canvas, Size size) {
    var paint = Paint()
      ..style = PaintingStyle.fill
      ..color = Colors.blue;
    //画布起点移动到屏幕中心
    canvas.translate(size.width / 2, size.height / 2);
//    canvas.drawCircle(Offset(0, 0), 50, paint);
    canvas.drawLine(
        Offset(20, 20),
        Offset(50, 50),
        paint
          ..color = Colors.red
          ..strokeWidth = 5
          ..strokeCap = StrokeCap.round);
  }

  ///Canvas 缩放变换
  void canvasGrid(Canvas canvas, Size size) {
    Paint gridPait; //画笔
    final double step = 20; //小格边长
    final double strokeWidth = .5; //线宽
    final Color color = Colors.grey; //线颜色
    gridPait = Paint()
      ..style = PaintingStyle.stroke
      ..strokeWidth = strokeWidth
      ..color = color;

    canvas.save();
    for (int i = 0; i < size.height / 2 / step; i++) {
      canvas.drawLine(Offset(0, 0), Offset(size.width / 2, 0), gridPait);
      canvas.translate(0, step);
    }
    canvas.restore();

    canvas.save();
    for (int i = 0; i < size.width / 2 / step; i++) {
      canvas.drawLine(Offset(0, 0), Offset(0, size.height / 2), gridPait);
      canvas.translate(step, 0);
    }
    canvas.restore();
  }

  ///画网格  todo 记得先把原点移动到中心位置
  void canvasBottomRight(Canvas canvas, Size size) {
    canvasGrid(canvas, size);

    ///沿X轴镜像
    canvas.save();
    canvas.scale(1, -1);
    canvasGrid(canvas, size);
    canvas.restore();

    ///沿Y轴镜像
    canvas.save();
    canvas.scale(-1, 1);
    canvasGrid(canvas, size);
    canvas.restore();

    ///原点镜像
    canvas.save();
    canvas.scale(-1, -1);
    canvasGrid(canvas, size);
    canvas.restore();
  }

  ///画一圈太阳光 2* pi 是一圈的弧度
  void drawDot(Canvas canvas) {
    Paint paint = Paint()
      ..color = Colors.orangeAccent
      ..strokeWidth = 10
      ..style = PaintingStyle.stroke;
    canvas.save();
    for (int i = 0; i < 12; i++) {
      canvas.drawLine(Offset(80, 0), Offset(100, 0), paint);
      //旋转是按照弧度来的
      canvas.rotate(2 * pi / 12);
    }
    canvas.restore();
  }

  final List<Offset> points = [
    Offset(-120, -20),
    Offset(-80, -80),
    Offset(-40, -40),
    Offset(0, -100),
    Offset(40, -140),
    Offset(80, -160),
    Offset(120, -100),
  ];