Flutter 绘图

文章目录

  • Flutter 绘图
    • 概述
    • 绘制线
    • 绘制点
    • 绘制矩形
    • 绘制圆角矩形
    • 绘制圆形
    • 绘制椭圆
    • 绘制弧
    • 绘制路径
    • 绘制文本
    • 绘制图片

Flutter 绘图

概述

  • Canvas(画布)用来在上面画图形的,如绘制点、线、矩形、圆形、路径、图像等。
  • Paint(画笔)用来设置画布上绘制图形的颜色、粗细、是否抗锯齿等作图风格。
  • 在Flutter中,绘图需要用到CustomPaintCustomPainterCustomPaint可以理解为画板,用于承载画布,CustomPainter可以理解为画布,承载绘制内容。

绘制线

Flutter 绘图_第1张图片

Container(
    width: MediaQuery.of(context).size.width,
    height: 200,
    color: Colors.white,
    child: CustomPaint(
        //定义画板大小
        size: const Size(200, 200),
        //配置画布
        painter: LinePainter(),
        //子节点,RepaintBoundary会创建一个新的图层layer,避免重复绘制
        child: const RepaintBoundary(
            child: Center(child: Text("hello world")),
        ),
    ),
)
class LinePainter extends CustomPainter {
    //定义画笔:画笔颜色、画笔宽度
    final Paint _paint = Paint()
        ..color = Colors.blue
        ..strokeWidth = 4;

    /// 绘制流程
    @override
    void paint(Canvas canvas, Size size) {
        canvas.drawLine(const Offset(20, 20), const Offset(100, 100), _paint);
    }

    /// 刷新是是否重绘
    @override
    bool shouldRepaint(covariant CustomPainter oldDelegate) {
        return false;
    }
}

绘制点

Flutter 绘图_第2张图片

Container(
    width: MediaQuery.of(context).size.width,
    height: 200,
    color: Colors.white,
    child: CustomPaint(
        size: const Size(200, 200),
        painter: PointPainter(),
    ),
)
class PointPainter extends CustomPainter {
    final Paint _paint = Paint()
        //画笔颜色
        ..color = Colors.blue
        //画笔笔头样式
        ..strokeCap = StrokeCap.round
        //抗锯齿
        ..isAntiAlias = true
        //填充样式
        ..style = PaintingStyle.fill
        //画笔宽度
        ..strokeWidth = 20;

    @override
    void paint(Canvas canvas, Size size) {
        canvas.drawPoints(
            ui.PointMode.points,
            [
                const Offset(50, 50),
                const Offset(100, 150),
                const Offset(150, 150),
            ],
            _paint);
    }

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

绘制矩形

Flutter 绘图_第3张图片

Container(
    width: MediaQuery.of(context).size.width,
    height: 200,
    color: Colors.white,
    child: CustomPaint(
        size: const Size(200, 200),
        painter: RectPainter(),
    ),
)
class RectPainter extends CustomPainter {
    final Paint _paint = Paint()
        ..color = Colors.blueAccent
        ..strokeCap = StrokeCap.round
        ..isAntiAlias = true
        ..style = PaintingStyle.fill
        ..strokeWidth = 2;

    @override
    void paint(Canvas canvas, Size size) {
        //方式一:设置左上右下4个顶点
        // Rect rect = const Rect.fromLTRB(20, 40, 150, 100);
        //方式二:设置2左上2个顶点和宽高
        // Rect rect = const Rect.fromLTWH(20, 40, 150, 100);
        //方式三:设置圆心和半径
        // Rect rect = Rect.fromCircle(center: const Offset(100, 100), radius: 50);
        //方式四:设置圆心和宽高
        Rect rect = Rect.fromCenter(center: const Offset(100, 100), width: 100, height: 100);
        canvas.drawRect(rect, _paint);
    }

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

绘制圆角矩形

Flutter 绘图_第4张图片

Container(
    width: MediaQuery.of(context).size.width,
    height: 200,
    color: Colors.white,
    child: CustomPaint(
        size: const Size(200, 200),
        painter: RRectPainter(),
    ),
)
class RRectPainter extends CustomPainter {
    final Paint _paint = Paint()
        ..color = Colors.blueAccent
        ..strokeCap = StrokeCap.round
        ..isAntiAlias = true
        ..style = PaintingStyle.fill
        ..strokeWidth = 2;

    @override
    void paint(Canvas canvas, Size size) {
        Rect rect = Rect.fromCenter(center: const Offset(100, 100), width: 100, height: 100);
        RRect rRect = RRect.fromRectAndRadius(rect, const Radius.circular(20));
        canvas.drawRRect(rRect, _paint);
    }

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

绘制圆形

Flutter 绘图_第5张图片

Container(
    width: MediaQuery.of(context).size.width,
    height: 200,
    color: Colors.white,
    child: CustomPaint(
        size: const Size(200, 200),
        painter: CirclePainter(),
    ),
)
class CirclePainter extends CustomPainter {
    final Paint _paint = Paint()
        ..color = Colors.blueAccent
        ..strokeCap = StrokeCap.round
        ..isAntiAlias = true
        ..style = PaintingStyle.stroke
        ..strokeWidth = 2;

    @override
    void paint(Canvas canvas, Size size) {
        canvas.drawCircle(const Offset(100, 100), 40, _paint);
    }

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

绘制椭圆

Flutter 绘图_第6张图片

Container(
    width: MediaQuery.of(context).size.width,
    height: 200,
    color: Colors.white,
    child: CustomPaint(
        size: const Size(200, 200),
        painter: OvalPainter(),
    ),
)
class OvalPainter extends CustomPainter {
    final Paint _paint = Paint()
        ..color = Colors.blueAccent
        ..strokeCap = StrokeCap.round
        ..isAntiAlias = true
        ..style = PaintingStyle.stroke
        ..strokeWidth = 2;

    @override
    void paint(Canvas canvas, Size size) {
        Rect rect = Rect.fromCenter(center: const Offset(150, 100), width: 200, height: 100);
        canvas.drawOval(rect, _paint);
    }

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

绘制弧

Flutter 绘图_第7张图片

Container(
    width: MediaQuery.of(context).size.width,
    height: 200,
    color: Colors.white,
    child: CustomPaint(
        size: const Size(200, 200),
        painter: ArcPainter(),
    ),
)
class ArcPainter extends CustomPainter {
    final Paint _paint = Paint()
        ..color = Colors.blueAccent
        ..style = PaintingStyle.stroke
        ..strokeWidth = 2;

    @override
    void paint(Canvas canvas, Size size) {
        const Rect rect = Rect.fromLTRB(50, 50, 150, 150);
        //参数依次是:矩形范围、开始弧度、结束弧度、是否连接圆心、画笔
        canvas.drawArc(rect, 0, 2, false, _paint);
    }

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

绘制路径

Flutter 绘图_第8张图片

Container(
    width: double.infinity,
    height: 200,
    color: Colors.white,
    child: CustomPaint(
        size: const Size(200, 200),
        painter: PathPainter(),
    ),
)
class PathPainter extends CustomPainter {
    final Paint _paint = Paint()
        ..color = Colors.black
        ..strokeCap = StrokeCap.round
        ..strokeJoin = StrokeJoin.round
        ..isAntiAlias = true
        ..style = PaintingStyle.stroke
        ..strokeWidth = 2;

    @override
    void paint(Canvas canvas, Size size) {
        final Path path = Path();
        path.moveTo(100, 80);
        path.lineTo(100, 150);
        path.lineTo(160, 150);
        path.close();
        canvas.drawPath(path, _paint);
    }

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

Flutter 绘图_第9张图片

Container(
    width: MediaQuery.of(context).size.width,
    height: 200,
    color: Colors.white,
    child: CustomPaint(
        size: const Size(200, 200),
        painter: PathPainter2(),
    ),
)
class PathPainter2 extends CustomPainter {
    final Paint _paint = Paint()
        ..color = Colors.black
        ..strokeCap = StrokeCap.round
        ..strokeJoin = StrokeJoin.round
        ..isAntiAlias = true
        ..style = PaintingStyle.stroke
        ..strokeWidth = 2;

    @override
    void paint(Canvas canvas, Size size) {
        final Path path = Path();
        path.moveTo(100, 80);
        path.lineTo(200, 80);
        path.addArc(
            Rect.fromCenter(center: const Offset(150, 80), width: 100, height: 100),
            0,
            0.5 * pi,
        );
        canvas.drawPath(path, _paint);
    }

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

绘制文本

Flutter 绘图_第10张图片

Container(
    width: MediaQuery.of(context).size.width,
    height: 200,
    color: Colors.white,
    child: CustomPaint(
        size: const Size(200, 200),
        painter: TextPainter(),
    ),
)
class TextPainter extends CustomPainter {
    @override
    void paint(Canvas canvas, Size size) {
        ui.ParagraphBuilder builder = ui.ParagraphBuilder(
            ui.ParagraphStyle(
                //文字方向
                textDirection: TextDirection.ltr,
                //最大行数
                maxLines: 2,
                //文本居中
                textAlign: TextAlign.center,
                //字体加粗
                fontWeight: FontWeight.bold,
                //字体样式
                fontStyle: FontStyle.normal,
                //字体大小
                fontSize: 24,
                //超出范围显示内容
                ellipsis: "...",
                //行间距
                height: 1.2,
                textHeightBehavior: const TextHeightBehavior(
                    applyHeightToFirstAscent: true,
                    applyHeightToLastDescent: true,
                ),
            ),
        );
        //设置文字样式
        builder.pushStyle(ui.TextStyle(
            color: Colors.red,
            fontSize: 20,
            height: 1,
            fontWeight: FontWeight.w500,
        ));
        String text = "床前明月光,疑是地上霜;举头望明月,低头思故乡。";
        builder.addText(text);
        //文本绘制最大宽度
        ui.ParagraphConstraints constraints = const ui.ParagraphConstraints(width: 300);
        ui.Paragraph paragraph = builder.build()..layout(constraints);
        //绘制文字
        canvas.drawParagraph(paragraph, const Offset(40, 40));
    }

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

绘制图片

Flutter 绘图_第11张图片

class ImagePaintPage extends StatefulWidget {
    const ImagePaintPage({Key? key}) : super(key: key);

    @override
    State createState() => _ImagePaintPageState();
}

class _ImagePaintPageState extends State {
    ui.Image? _image;

    @override
    void initState() {
        super.initState();
        loadImage();
    }

    loadImage() async {
        // _image = await loadImageByAssets();
        _image = await loadImageByNet();
        if (!mounted) return;
        setState(() {});
    }

    @override
    Widget build(BuildContext context) {
        return Column(
            children: [
                const Text("绘制图片"),
                Container(
                    width: MediaQuery.of(context).size.width,
                    height: 200,
                    color: Colors.white,
                    child: Center(
                        child: Stack(
                            children: [
                                _image == null
                                ? const CircularProgressIndicator()
                                : CustomPaint(
                                    size: const Size(200, 200),
                                    painter: ImagePainter(_image!),
                                ),
                            ],
                        ),
                    ),
                ),
            ],
        );
    }

    /// 加载Assets图片
    Future loadImageByAssets() async {
        AssetImage assetImage = const AssetImage("assets/images/bird.jpg");
        Completer completer = Completer();
        ImageStream imageStream = assetImage.resolve(ImageConfiguration.empty);
        late ImageStreamListener listener;
        listener = ImageStreamListener((ImageInfo imageInfo, bool synchronousCall) {
            final ui.Image image = imageInfo.image;
            completer.complete(image);
            imageStream.removeListener(listener);
        });
        imageStream.addListener(listener);
        return completer.future;
    }

    /// 加载网络图片
    Future loadImageByNet() async {
        String imageUrl = "https://www.baidu.com/img/PCtm_d9c8750bed0b3c7d089fa7d55720d6cf.png";
        NetworkImage networkImage = NetworkImage(imageUrl);
        Completer completer = Completer();
        ImageStream imageStream = networkImage.resolve(ImageConfiguration.empty);
        late ImageStreamListener listener;
        listener = ImageStreamListener((ImageInfo imageInfo, bool synchronousCall) {
            final ui.Image image = imageInfo.image;
            completer.complete(image);
            imageStream.removeListener(listener);
        });
        imageStream.addListener(listener); //添加监听
        return completer.future;
    }
}

class ImagePainter extends CustomPainter {
    final Paint _paint = Paint()..isAntiAlias = true;

    final ui.Image _image;

    ImagePainter(this._image);

    @override
    void paint(Canvas canvas, Size size) {
        //原图区域,一般传原图的宽高
        Rect src = const Offset(0.0, 0.0) & Size(_image.width.toDouble(), _image.height.toDouble());
        //目标显示区域
        Rect dst = const Offset(0.0, 0.0) & const Size(200, 200);
        canvas.drawImageRect(_image, src, dst, _paint);
    }

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

你可能感兴趣的:(flutter,绘制,CustomPaint,CustomPainter)