Flutter高级图像绘制插件image_painter_extended的使用

发布于 1周前 作者 gougou168 来自 Flutter

Flutter高级图像绘制插件image_painter_extended的使用

这是一个允许用户在图像上进行绘制的Flutter包。它是painter2包的一个扩展,具有缩放和绘制功能。

特性

该组件支持以下功能:

  • 更改前景色和背景色
  • 设置背景图像
  • 更改绘制路径的粗细
  • 导出你的绘画为PNG格式
  • 撤销/重做绘制路径
  • 清除整个绘图
  • 缩放和平移图像

安装

在你的Flutter项目的pubspec.yaml文件中添加依赖:

dependencies:
  image_painter_extended: any

然后导入它:

import 'package:image_painter_extended/image_painter_extended.dart';

使用

为了使用这个插件,首先创建一个控制器并可选地创建一个键:

GlobalKey<ImagePainterState> painterKey = GlobalKey<ImagePainterState>();
PainterController controller = PainterController();
controller.thickness = 5.0; // 设置画笔的粗细,默认为1.0
controller.backgroundColor = Colors.green; // 背景颜色在设置了背景图像时会被忽略
controller.backgroundImage = Image.network(...); // 设置背景图像。你可以像平常一样加载图像:从资源文件、网络或内存中加载。

该控制器将处理所有绘制空间的属性。键用于刷新小部件的状态,如果你决定以编程方式平移和缩放图像。

然后,为了显示绘制区域,创建一个内联的ImagePainter小部件,并给它一个之前创建的控制器的引用:

ImagePainter(controller, key: painterKey)

通过导出绘画为PNG格式,你会得到一个表示最终文件字节的Uint8List对象:

await controller.getPNGBytes();

你还可以使用getPathBytes()函数获取路径而不包含图像。

库本身不处理保存最终图像。

完整示例

下面是一个完整的示例代码,展示了如何使用image_painter_extended插件。

import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:image_painter_extended/image_painter_extended.dart';
import 'package:flutter_switch/flutter_switch.dart';
import 'package:path_provider/path_provider.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  [@override](/user/override)
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: DemoPage(),
    );
  }
}

class DemoPage extends StatefulWidget {
  [@override](/user/override)
  _DemoPageState createState() => _DemoPageState();
}

class _DemoPageState extends State<DemoPage> {
  Image bg = Image.asset("lib/assets/img.jpg", fit: BoxFit.cover);
  GlobalKey<ImagePainterState> painterKey = GlobalKey<ImagePainterState>();

  double scale = 1;
  double translateX = 0;
  double translateY = 0;
  String savepath = "";

  bool buttonCOntrol = false;
  bool isDrawmode = true;
  PainterController _controller;

  [@override](/user/override)
  void initState() {
    super.initState();
    _controller = _newController();
  }

  PainterController _newController() {
    PainterController controller = new PainterController();
    controller.backgroundImage = bg;
    controller.thickness = 5.0;
    controller.backgroundColor = Colors.transparent;
    return controller;
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
        body: Column(
      children: [
        Container(
          child: Center(
              child: AspectRatio(
                  aspectRatio: 1.0,
                  child: ImagePainter(
                    _controller,
                    key: painterKey,
                  ))),
        ),
        Text(savepath),
        Expanded(
            child: SingleChildScrollView(
                child: Column(children: [
          Text("如何控制"),
          howTOControl(),
          Text("绘制选项"),
          basicOptions(),
          !buttonCOntrol ? Text("模式") : Container(),
          !buttonCOntrol ? switchOption() : Container(),
          buttonCOntrol ? Text("控制按钮") : Container(),
          buttonCOntrol ? optionsBUtton() : Container(),
        ]))),
      ],
    ));
  }

  Widget howTOControl() {
    return Row(
      mainAxisSize: MainAxisSize.max,
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        Text("按钮模式"),
        FlutterSwitch(
          value: buttonCOntrol,
          onToggle: (val) {
            setState(() {
              buttonCOntrol = val;
              isDrawmode = true;
            });
            _controller.drawMode = true;
            translateX = 0;
            translateY = 0;
            scale = 1;
            transformMatrix();
          },
        ),
      ],
    );
  }

  Widget switchOption() {
    return Row(
      mainAxisSize: MainAxisSize.max,
      mainAxisAlignment: MainAxisAlignment.spaceEvenly,
      children: [
        Text("变换模式"),
        FlutterSwitch(
          value: isDrawmode,
          inactiveColor: Colors.green,
          onToggle: (val) {
            setState(() {
              isDrawmode = val;
            });
            _controller.drawMode = val;
            painterKey.currentState.setState(() {});
          },
        ),
        Text("绘制模式"),
      ],
    );
  }

  Widget basicOptions() {
    return Wrap(
      spacing: 10,
      children: [
        ElevatedButton(
            onPressed: () {
              _controller.undo();
            },
            child: Text("撤销")),
        ElevatedButton(
            onPressed: () {
              _controller.redo();
            },
            child: Text("重做")),
        ElevatedButton(
            onPressed: () async {
              final String path = (await getApplicationDocumentsDirectory()).path;
              setState(() {
                savepath = "Saved to " + path;
              });

              print(path);
              // 仅保存路径
              Uint8List img = await _controller.getPathBytes();
              File('$path/image1.png').writeAsBytes(img);
            },
            child: Text("保存路径")),
        ElevatedButton(
            onPressed: () async {
              final String path = (await getApplicationDocumentsDirectory()).path;
              setState(() {
                savepath = "Saved to " + path;
              });

              translateX = 0;
              translateY = 0;
              scale = 1;
              transformMatrix();
              await Future.delayed(Duration(milliseconds: 100), () {});

              print(path);
              // 保存完整图像
              Uint8List pngBytes = await _controller.getPNGBytes();
              File('$path/image2.png').writeAsBytes(pngBytes);
            },
            child: Text("保存图像")),
        ElevatedButton(
            onPressed: () {
              _controller.clear();
            },
            child: Text("清除")),
      ],
    );
  }

  Widget optionsBUtton() {
    return Column(
      children: [
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: [
            ElevatedButton(
                onPressed: () {
                  if (scale < 2.5) {
                    scale += 0.5;
                    transformMatrix();
                  }
                },
                child: Text("+")),
            ElevatedButton(
                onPressed: () {
                  if (scale > 1) {
                    scale -= 0.5;
                    transformMatrix();
                  }
                },
                child: Text("-")),
            ElevatedButton(
                onPressed: () {
                  translateX = 0;
                  translateY = 0;
                  scale = 1;
                  transformMatrix();
                },
                child: Text("重置变换"))
          ],
        ),
        Row(
          mainAxisAlignment: MainAxisAlignment.spaceAround,
          children: [
            ElevatedButton(
                onPressed: () {
                  translateY += 2;
                  transformMatrix();
                },
                child: Text("向上")),
            ElevatedButton(
                onPressed: () {
                  translateY -= 2;
                  transformMatrix();
                },
                child: Text("向下")),
            ElevatedButton(
                onPressed: () {
                  translateX -= 2;
                  transformMatrix();
                },
                child: Text("向左")),
            ElevatedButton(
                onPressed: () {
                  translateX += 2;
                  transformMatrix();
                },
                child: Text("向右"))
          ],
        ),
      ],
    );
  }

  void transformMatrix() {
    _controller.interactionController.value = Matrix4(
      scale,
      0,
      0,
      0,
      0,
      scale,
      0,
      0,
      0,
      0,
      1,
      0,
      translateX,
      translateY,
      0,
      1,
    );
    painterKey.currentState.setState(() {});
  }
}

更多关于Flutter高级图像绘制插件image_painter_extended的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter高级图像绘制插件image_painter_extended的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中使用image_painter_extended插件进行高级图像绘制的示例代码。image_painter_extended插件提供了一些高级功能,允许你在Canvas上进行复杂的图像绘制操作。

首先,确保你已经在pubspec.yaml文件中添加了image_painter_extended依赖:

dependencies:
  flutter:
    sdk: flutter
  image_painter_extended: ^最新版本号  # 请替换为实际的最新版本号

然后,运行flutter pub get来安装依赖。

以下是一个简单的示例,展示了如何使用image_painter_extended在Flutter应用中绘制一张图片并进行一些基本的变换操作:

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

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Image Painter Extended Example'),
        ),
        body: CustomPaint(
          size: Size(double.infinity, double.infinity),
          painter: ImagePainterExtended(
            imageProvider: NetworkImage('https://example.com/image.jpg'), // 替换为你的图片URL
            onLoad: (imageInfo) {
              // 图片加载完成后的回调,可以在这里进行额外的设置
              print('Image loaded: ${imageInfo.image.width}x${imageInfo.image.height}');
            },
            paintImage: (Canvas canvas, Rect rect, ImageProvider image) {
              // 自定义绘制逻辑
              final paint = Paint()
                ..isAntiAlias = true
                ..filterQuality = FilterQuality.high;

              // 绘制原始图片
              canvas.drawImage(image, rect.topLeft, paint);

              // 示例:在图片上绘制一个半透明矩形覆盖层
              final rectPaint = Paint()
                ..color = Color(0x55000000) // 半透明黑色
                ..style = PaintingStyle.fill;
              canvas.drawRect(rect, rectPaint);

              // 示例:在图片上绘制文本
              final textPainter = TextPainter(
                text: TextSpan(
                  text: 'Hello Flutter!',
                  style: TextStyle(color: Colors.white, fontSize: 24),
                ),
                textAlign: TextAlign.center,
                textDirection: TextDirection.ltr,
              )..layout(minWidth: 0, maxWidth: double.infinity);

              final textPosition = rect.center - Offset(textPainter.width / 2, textPainter.height / 2);
              textPainter.paint(canvas, textPosition);
            },
          ),
        ),
      ),
    );
  }
}

在这个示例中,我们做了以下几件事:

  1. 引入必要的包:我们导入了flutter/material.dartimage_painter_extended包。
  2. 定义MyApp组件:这是我们的主应用组件,其中包含一个Scaffold,并在其body中使用CustomPaint组件。
  3. 使用ImagePainterExtended:在CustomPaintpainter属性中,我们实例化了ImagePainterExtended,并提供了图片的网络地址。
  4. 自定义绘制逻辑:在paintImage回调中,我们首先绘制了原始图片,然后在图片上添加了一个半透明的矩形覆盖层,并绘制了文本“Hello Flutter!”。

这个示例展示了如何使用image_painter_extended进行基本的图像绘制和自定义操作。你可以根据需要进一步扩展和修改这个示例,以实现更复杂的图像绘制效果。

回到顶部