Flutter擦除恢复功能插件erase_restore的使用

Flutter擦除恢复功能插件erase_restore的使用

erase_restore 是一个 Flutter 包,它提供了简单且可定制的方式来实现图像的擦除和撤销/重做功能。通过这个包,您可以轻松地为您的 Flutter 应用添加图像擦除工具,允许用户使用手指或触控笔擦除图像的一部分。此外,该包还提供了撤销和重做功能,允许用户根据需要撤销或重做他们的擦除笔画。

如何使用

开始使用

在您的 Flutter 项目的 pubspec.yaml 文件中,添加以下依赖:

dependencies:
  ...
  erase_restore: <latest_version>

在您的库中添加以下导入语句:

import 'package:erase_restore/erase_restore.dart';

初始化 EraseRestoreView

import 'package:erase_restore/erase_restore.dart';

final EraseRestoreController controller = EraseRestoreController();

Future<EraseRestoreModel?> _getModel() async {
  final bgBuffer = await rootBundle.load('assets/bg.png');
  final bgImage = await decodeImageFromList(bgBuffer.buffer.asUint8List());

  final originalBuffer = await rootBundle.load('assets/original.png');
  final originalImage = await decodeImageFromList(originalBuffer.buffer.asUint8List());

  final clipBuffer = await rootBundle.load('assets/clip.png');
  final clipImage = await decodeImageFromList(clipBuffer.buffer.asUint8List());

  final maskImageData = await EraseRestoreModel.getMaskImageData(
      clipBuffer.buffer.asUint8List());
  if (maskImageData == null) return null;
  return EraseRestoreModel(
    clipImage: clipImage,
    originalImage: originalImage,
    bgImage: bgImage,
    maskImage: maskImageData.image,
  );
}

// 使用 FutureBuilder 加载模型并构建 EraseRestoreView
return FutureBuilder<EraseRestoreModel?>(
  future: _getModel(),
  builder: (context, snapshot) {
    if (!snapshot.hasData) return const SizedBox.shrink();
    final data = snapshot.data;
    if (data == null) return const SizedBox.shrink();
    return EraseRestoreView(
      model: data,
      controller: controller,
      maskColor: const Color.fromARGB(74, 248, 13, 35),
      previousStepEnable: (enable) {
        setState(() {
          _previousStepEnable = enable;
        });
      },
      nextStepEnable: (enable) {
        setState(() {
          _nextStepEnable = enable;
        });
      },
    );
  },
);

所有操作

// 切换编辑类型(擦除或恢复)
void switchEditType(EditType editType)

// 撤销上一步
void previousStep()

// 重做下一步
void nextStep()

// 更新笔画宽度
void updateStokeWidth(double width)

// 截取屏幕快照
Future<ui.Image?> takeScreenShot()

完整示例 Demo

import 'package:erase_restore/erase_restore.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

void main() => runApp(const MyApp());

class MyApp extends StatelessWidget {
  const MyApp({
    super.key,
  });

  [@override](/user/override)
  Widget build(BuildContext context) {
    return const MaterialApp(
      home: EraseRestoreScreen(),
    );
  }
}

class EraseRestoreScreen extends StatefulWidget {
  const EraseRestoreScreen({
    super.key,
  });

  [@override](/user/override)
  State<StatefulWidget> createState() => _EraseRestoreScreenState();
}

class _EraseRestoreScreenState extends State<EraseRestoreScreen> {
  final EraseRestoreController controller = EraseRestoreController();
  double strokeWidth = 20;

  bool _previousStepEnable = false;
  bool _nextStepEnable = false;

  Future<EraseRestoreModel?> _getModel() async {
    final bgBuffer = await rootBundle.load('assets/bg.png');
    final bgImage = await decodeImageFromList(bgBuffer.buffer.asUint8List());

    final originalBuffer = await rootBundle.load('assets/original.png');
    final originalImage = await decodeImageFromList(originalBuffer.buffer.asUint8List());

    final clipBuffer = await rootBundle.load('assets/clip.png');
    final clipImage = await decodeImageFromList(clipBuffer.buffer.asUint8List());

    final maskImageData = await EraseRestoreModel.getMaskImageData(
        clipBuffer.buffer.asUint8List());
    if (maskImageData == null) return null;
    return EraseRestoreModel(
      clipImage: clipImage,
      originalImage: originalImage,
      bgImage: bgImage,
      maskImage: maskImageData.image,
    );
  }

  [@override](/user/override)
  Widget build(BuildContext context) {
    return Scaffold(
      body: Column(
        crossAxisAlignment: CrossAxisAlignment.center,
        children: [
          const SizedBox(height: 100),
          Container(
            height: 400,
            color: Colors.red,
            child: FutureBuilder<EraseRestoreModel?>(
              future: _getModel(),
              builder: (context, snapshot) {
                if (!snapshot.hasData) return const SizedBox.shrink();
                final data = snapshot.data;
                if (data == null) return const SizedBox.shrink();
                return EraseRestoreView(
                  model: data,
                  controller: controller,
                  maskColor: const Color.fromARGB(74, 248, 13, 35),
                  previousStepEnable: (enable) {
                    setState(() {
                      _previousStepEnable = enable;
                    });
                  },
                  nextStepEnable: (enable) {
                    setState(() {
                      _nextStepEnable = enable;
                    });
                  },
                );
              },
            ),
          ),
          ElevatedButton(
            onPressed: () {
              controller.switchEditType(EditType.erase);
            },
            child: const Text('Erase'),
          ),
          ElevatedButton(
            onPressed: () {
              controller.switchEditType(EditType.restore);
            },
            child: const Text('Restore'),
          ),
          ElevatedButton(
            onPressed: _previousStepEnable
                ? () {
                    controller.previousStep();
                  }
                : null,
            child: const Text('Previous Step'),
          ),
          ElevatedButton(
            onPressed: _nextStepEnable
                ? () {
                    controller.nextStep();
                  }
                : null,
            child: const Text('Next Step'),
          ),
          ElevatedButton(
            onPressed: () {
              strokeWidth += 1;
              controller.updateStokeWidth(strokeWidth);
            },
            child: const Text('Stroke width +1'),
          ),
          ElevatedButton(
            onPressed: () {
              if (strokeWidth <= 0) return;
              strokeWidth -= 1;
              controller.updateStokeWidth(strokeWidth);
            },
            child: const Text('Stroke width -1'),
          ),
          ElevatedButton(
            onPressed: () async {
              final navigatorState = Navigator.of(context);
              final result = await controller.takeScreenShot();
              if (result == null) return;
              navigatorState.push(
                MaterialPageRoute<void>(
                  builder: (BuildContext ctx) => Container(
                    color: Colors.white,
                    child: Center(
                      child: RawImage(
                        image: result,
                      ),
                    ),
                  ),
                ),
              );
            },
            child: const Text('Take Screenshot'),
          ),
        ],
      ),
    );
  }
}

更多关于Flutter擦除恢复功能插件erase_restore的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html

1 回复

更多关于Flutter擦除恢复功能插件erase_restore的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html


当然,以下是如何在Flutter项目中集成和使用erase_restore插件的示例代码。erase_restore插件允许你在Flutter应用中实现擦除和恢复功能,这对于绘画应用或者需要撤销操作的应用非常有用。

步骤 1: 添加依赖

首先,你需要在pubspec.yaml文件中添加erase_restore依赖:

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

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

步骤 2: 导入插件

在你的Dart文件中导入插件:

import 'package:erase_restore/erase_restore.dart';

步骤 3: 使用EraseRestore包装你的绘画区域

假设你有一个自定义的绘画组件,你需要使用EraseRestore包装它,以便管理擦除和恢复操作。

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

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

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(
          title: Text('Erase Restore Example'),
        ),
        body: EraseRestoreWidget(),
      ),
    );
  }
}

class EraseRestoreWidget extends StatefulWidget {
  @override
  _EraseRestoreWidgetState createState() => _EraseRestoreWidgetState();
}

class _EraseRestoreWidgetState extends State<EraseRestoreWidget> {
  late EraseRestoreController _controller;

  @override
  void initState() {
    super.initState();
    _controller = EraseRestoreController();
  }

  @override
  Widget build(BuildContext context) {
    return EraseRestore(
      controller: _controller,
      child: Stack(
        children: [
          CustomPaint(
            size: Size.infinite,
            painter: MyPainter(_controller),
          ),
          GestureDetector(
            onPanUpdate: (details) {
              // 假设这是你的绘画逻辑
              // 这里你需要根据_controller的状态来决定是否擦除或正常绘画
              setState(() {}); // 触发重绘
            },
            onLongPressStart: (details) {
              // 开始擦除
              _controller.startErase();
            },
            onLongPressEnd: (details) {
              // 结束擦除
              _controller.stopErase();
            },
          ),
        ],
      ),
    );
  }
}

class MyPainter extends CustomPainter {
  final EraseRestoreController _controller;

  MyPainter(this._controller);

  @override
  void paint(Canvas canvas, Size size) {
    final Paint paint = Paint()
      ..color = Colors.black
      ..strokeWidth = 5.0
      ..style = PaintingStyle.stroke;

    // 这里假设你有一个路径列表来保存绘画路径
    // 根据_controller的状态来决定是否绘制这些路径
    // 例如,如果处于擦除状态,则不绘制某些路径
    // 由于这是一个简单示例,我们只绘制一个静态矩形
    canvas.drawRect(
      Rect.fromLTWH(50, 50, 200, 100),
      paint,
    );
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return true; // 在实际应用中,你可能需要更精细的控制
  }
}

注意事项

  1. 擦除逻辑:在实际应用中,你可能需要更复杂的擦除逻辑。例如,你可能希望只擦除特定路径或特定区域内的内容。这通常涉及到保存和恢复路径列表的状态。

  2. 性能优化:频繁的重绘可能会影响性能。在复杂的应用中,你可能需要考虑使用RepaintBoundary或其他技术来优化性能。

  3. 撤销/重做:虽然erase_restore插件主要用于擦除和恢复功能,但你也可以基于它的状态管理来实现撤销/重做功能。

以上代码提供了一个基本的框架,展示了如何在Flutter中使用erase_restore插件来实现擦除和恢复功能。你可以根据具体需求进一步扩展和定制。

回到顶部