如何在Flutter中从画布裁剪圆形(或Square或Hexagon)区域 [英] How to crop circular(or Square or Hexagon ) area from canvas in Flutter

查看:395
本文介绍了如何在Flutter中从画布裁剪圆形(或Square或Hexagon)区域的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我要裁剪矩形的图像文件,并将其制成圆形,正方形或六边形,然后将其另存为本地图像文件.我有一个位图,我想从该位图裁剪圆形或六边形区域.圆外的所有像素都应该是透明的.我该怎么办?

I want to crop a rectangular image-file and make it circular or square or hexagon shape and save it as image-file locally. I have a bitmap and I want to crop a circular or hexagon region from this bitmap. All pixels outside the circle should be transparent. How can I do this?

我在 android 中发现了类似的问题平台. 但是找不到能真正帮助或指导我实现目标的好的资源.请分享给我实现此结果的想法.

I found the similar question in android platform. But unable to find a good resource that really help or direct me to achieve this in flutter. Please share me the idea to achieve this result.

推荐答案

这些简单的步骤可获得所需的结果.

  1. 创建 PictureRecorder .
  2. 使用 PictureRecorder 创建画布.
  3. 使用 canvas.drawCircle()在画布中绘制圆.
  4. 在PictureRecorder上调用 endRecording()来获取图片.
  5. 在图片上调用 toImage().
  6. 将图像转换为 toByteData().
  7. 使用 getApplicationDocumentsDirectory()在本地保存图像.
  1. Create a PictureRecorder.
  2. Create a Canvas with your PictureRecorder.
  3. Draw circle in canvas using canvas.drawCircle().
  4. Call endRecording() on the PictureRecorder to get a Picture.
  5. Call toImage() on the Picture.
  6. Convert image toByteData() .
  7. Save image locally using getApplicationDocumentsDirectory().

画布屏幕

将图像画布另存为png

完整源代码:

        import 'dart:io';

        import 'package:flutter/material.dart';
        import 'dart:ui' as ui;
        import 'package:flutter/services.dart' show rootBundle;
        import 'dart:async';
        import 'dart:typed_data';
        import 'dart:math' as math;
        import 'package:path/path.dart';
        import 'package:path_provider/path_provider.dart';

        class CustomImageCanvas extends StatefulWidget {
          CustomImageCanvas({Key key, this.title}) : super(key: key);

          final String title;

          @override
          _CustomImageCanvasState createState() => _CustomImageCanvasState();
        }

        class _CustomImageCanvasState extends State<CustomImageCanvas> {
          ui.Image image;
          bool isImageloaded = false;
          void initState() {
            super.initState();
            init();
          }

          Future<Null> init() async {
            final ByteData data = await rootBundle.load('assets/image.jpeg');
            image = await loadImage(Uint8List.view(data.buffer));
          }

          Future<ui.Image> loadImage(List<int> img) async {
            final Completer<ui.Image> completer = Completer();
            ui.decodeImageFromList(img, (ui.Image img) {
              setState(() {
                isImageloaded = true;
              });
              return completer.complete(img);
            });
            return completer.future;
          }

          Widget _buildImage() {
            if (this.isImageloaded) {
              return CustomPaint(
                painter: PngImagePainter(image: image),
              );
            } else {
              return Center(child: Text('loading'));
            }
          }

          @override
          Widget build(BuildContext context) {
            return Scaffold(
                appBar: AppBar(
                  title: Text(widget.title),
                ),
                body: Container(
                  child: _buildImage(),
                ));
          }
        }

        class PngImagePainter extends CustomPainter {
          PngImagePainter({
            this.image,
          });

          ui.Image image;

          @override
          void paint(Canvas canvas, Size size) {
            _drawCanvas(size, canvas);
            _saveCanvas(size);
          }

          Canvas _drawCanvas(Size size, Canvas canvas) {
            final center = Offset(150, 50);
            final radius = math.min(size.width, size.height) / 8;

            // The circle should be paint before or it will be hidden by the path
            Paint paintCircle = Paint()..color = Colors.black;
            Paint paintBorder = Paint()
              ..color = Colors.white
              ..strokeWidth = size.width / 36
              ..style = PaintingStyle.stroke;
            canvas.drawCircle(center, radius, paintCircle);
            canvas.drawCircle(center, radius, paintBorder);

            double drawImageWidth = 0;
            var drawImageHeight = -size.height * 0.8;

            Path path = Path()
              ..addOval(Rect.fromLTWH(drawImageWidth, drawImageHeight,
                  image.width.toDouble(), image.height.toDouble()));

            canvas.clipPath(path);

            canvas.drawImage(image, Offset(drawImageWidth, drawImageHeight), Paint());
            return canvas;
          }

          _saveCanvas(Size size) async {
            var pictureRecorder = ui.PictureRecorder();
            var canvas = Canvas(pictureRecorder);
            var paint = Paint();
            paint.isAntiAlias = true;

            _drawCanvas(size, canvas);

            var pic = pictureRecorder.endRecording();
            ui.Image img = await pic.toImage(image.width, image.height);
            var byteData = await img.toByteData(format: ui.ImageByteFormat.png);
            var buffer = byteData.buffer.asUint8List();

            // var response = await get(imgUrl);
            var documentDirectory = await getApplicationDocumentsDirectory();
            File file = File(join(documentDirectory.path,
                '${DateTime.now().toUtc().toIso8601String()}.png'));
            file.writeAsBytesSync(buffer);

            print(file.path);
          }

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

这篇关于如何在Flutter中从画布裁剪圆形(或Square或Hexagon)区域的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆