Flutter图像绘制插件draw_on_image_plugin的使用
Flutter图像绘制插件draw_on_image_plugin的使用
获取开始
首先,创建插件实例:
DrawOnImagePlugin _plugin = DrawOnImagePlugin();
然后,创建一个数据类来保存绘制参数,例如字体大小、内边距、颜色等:
var writeData = WriteImageData(
text,
imageBytes,
left: left,
right: right,
top: top,
bottom: bottom,
color: color.value,
fontSize: size
);
其中,text
和 imageBytes
是必需的参数,其余参数是可选的。
接下来,将这些数据传递给插件:
String path = await _plugin.writeTextOnImage(writeData);
这样你就会得到一个新的带有文本的图片路径。你需要自己管理(移动、重命名、删除)新生成的文件。
更多详细信息可以在 示例 中查看。
完整示例
下面是完整的示例代码:
import 'dart:io';
import 'dart:typed_data';
import 'dart:ui';
import 'package:draw_on_image_plugin/draw_on_image_plugin.dart';
import 'package:flutter/material.dart';
import 'dart:async';
import 'package:flutter/services.dart';
import 'package:flutter_colorpicker/flutter_colorpicker.dart';
void main() {
runApp(MaterialApp(
home: MyApp(),
));
}
class MyApp extends StatefulWidget {
[@override](/user/override)
_MyAppState createState() => _MyAppState();
}
class _MyAppState extends State<MyApp> {
DrawOnImagePlugin _plugin = DrawOnImagePlugin();
String? _pathToNewFile;
Future<void> _sendPluginRequest(BasicDrawParameters params) async {
ByteData imageBytes = await rootBundle.load("assets/images/test_image.png");
String fileName = await _plugin.writeTextOnImage(
WriteImageData(
params.text,
imageBytes,
left: params.left,
right: params.right,
top: params.top,
bottom: params.bottom,
color: params.color.value,
fontSize: params.size
));
setState(() {
_pathToNewFile = fileName;
});
}
[@override](/user/override)
Widget build(BuildContext context) {
var dimensions = ScreenDimensions(context);
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('Plugin example app'),
),
body: Column(
children: [
Container(
width: dimensions.width,
height: dimensions.withoutSafeAreaHeight * 0.75,
child: _pathToNewFile == null
? _buildInitialScreen()
: _buildMainScreen(),
),
_buildButton()
]
)
),
);
}
Widget _buildButton() {
return ElevatedButton(
onPressed: () async {
_pathToNewFile = null;
BasicDrawParameters params = await Navigator.of(context).push(
MaterialPageRoute(
builder: (context) => DrawOptionsDialog()
)
);
_sendPluginRequest(params);
},
child: Container(
color: Colors.blue,
padding: const EdgeInsets.all(10.0),
child: const Text("Draw"),
)
);
}
Widget _buildInitialScreen() {
return Image.asset(
"assets/images/test_image.png",
fit: BoxFit.contain
);
}
Widget _buildMainScreen() {
return Image.file(
File(_pathToNewFile ?? ""),
fit: BoxFit.contain
);
}
}
class DrawOptionsDialog extends StatefulWidget {
const DrawOptionsDialog({ Key? key }) : super(key: key);
[@override](/user/override)
_DrawOptionsDialogState createState() => _DrawOptionsDialogState();
}
class _DrawOptionsDialogState extends State<DrawOptionsDialog> {
final TextEditingController _drawTextController = new TextEditingController();
final TextEditingController _fontSizeController = new TextEditingController();
final TextEditingController _leftController = new TextEditingController();
final TextEditingController _rightController = new TextEditingController();
final TextEditingController _topController = new TextEditingController();
final TextEditingController _bottomController = new TextEditingController();
Color _selectedColor = Colors.red;
[@override](/user/override)
Widget build(BuildContext context) {
return Scaffold(
body: SafeArea(
child: SingleChildScrollView(
child: Column(
children: [
_buildTextInputField(),
_buildTextSizeField(),
_buildPaddingsRow(),
_buildColorPicker(),
_buildButton()
]
)
),
),
);
}
Widget _buildTextInputField() {
return Padding(
padding: const EdgeInsets.all(20.0),
child: TextField(
controller: _drawTextController,
keyboardType: TextInputType.multiline,
maxLines: null,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Text to draw',
)
)
);
}
Widget _buildTextSizeField() {
return Padding(
padding: const EdgeInsets.all(20.0),
child: TextField(
controller: _fontSizeController,
keyboardType: TextInputType.number,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Font Size',
)
)
);
}
Widget _buildColorPicker() {
return ColorPicker(
pickerColor: _selectedColor,
onColorChanged: _onColorChange,
showLabel: true,
pickerAreaHeightPercent: 0.8,
);
}
Widget _buildButton() {
return ElevatedButton(
onPressed: _doneButtonTap,
child: Container(
color: Colors.blue,
padding: const EdgeInsets.all(10.0),
child: const Text("Done"),
)
);
}
Widget _buildPaddingsRow() {
return Row(
children: [
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
controller: _leftController,
keyboardType: TextInputType.number,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Left',
)
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
controller: _rightController,
keyboardType: TextInputType.number,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Right',
)
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
controller: _topController,
keyboardType: TextInputType.number,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Top',
)
),
),
),
Expanded(
child: Padding(
padding: const EdgeInsets.all(8.0),
child: TextField(
controller: _bottomController,
keyboardType: TextInputType.number,
decoration: InputDecoration(
border: OutlineInputBorder(),
labelText: 'Bottom',
)
),
),
)
]
);
}
void _onColorChange(Color newColor) {
_selectedColor = newColor;
}
void _doneButtonTap() {
FocusScope.of(context).unfocus();
BasicDrawParameters? parameters = _buildDrawParameters();
if (parameters == null) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: Text("Error!"),
content: Text("Error during creating parameters."),
actions: [
ElevatedButton(
child: Text("OK"),
onPressed: () => Navigator.of(context).pop()
)
]
);
}
);
} else {
Navigator.pop(context, parameters);
}
}
BasicDrawParameters? _buildDrawParameters() {
BasicDrawParameters? parameters;
try {
int left = int.parse(_leftController.text);
int right = int.parse(_rightController.text);
int top = int.parse(_topController.text);
int bottom = int.parse(_bottomController.text);
int size = int.parse(_fontSizeController.text);
parameters = BasicDrawParameters(
_drawTextController.text,
_selectedColor,
size,
left,
right,
top,
bottom
);
} catch(error) {
print("Error during building parameters : $error");
}
return parameters;
}
}
class ScreenDimensions {
double width = 0;
double fullHeight = 0;
double withoutSafeAreaHeight = 0;
ScreenDimensions(BuildContext context) {
width = MediaQuery.of(context).size.width;
fullHeight = MediaQuery.of(context).size.height;
var padding = MediaQuery.of(context).padding;
withoutSafeAreaHeight = fullHeight - padding.top - padding.bottom;
}
}
class BasicDrawParameters {
final Color color;
final String text;
final int size;
final int left;
final int right;
final int top;
final int bottom;
const BasicDrawParameters(
this.text,
this.color,
this.size,
this.left,
this.right,
this.top,
this.bottom,
);
}
更多关于Flutter图像绘制插件draw_on_image_plugin的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter图像绘制插件draw_on_image_plugin的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
当然,下面是一个关于如何使用 draw_on_image_plugin
的示例代码。这个插件允许你在图像上进行绘制操作,比如添加文字、线条、形状等。首先,确保你已经在 pubspec.yaml
文件中添加了该插件的依赖:
dependencies:
flutter:
sdk: flutter
draw_on_image: ^x.y.z # 请替换为最新的版本号
然后,运行 flutter pub get
来获取依赖。
以下是一个完整的示例代码,展示如何使用 draw_on_image_plugin
在图像上绘制:
import 'package:flutter/material.dart';
import 'package:draw_on_image/draw_on_image.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text('Draw on Image Example'),
),
body: DrawOnImageExample(),
),
);
}
}
class DrawOnImageExample extends StatefulWidget {
@override
_DrawOnImageExampleState createState() => _DrawOnImageExampleState();
}
class _DrawOnImageExampleState extends State<DrawOnImageExample> {
final GlobalKey _drawImageKey = GlobalKey();
late List<OverlayEntry> _overlayEntries;
@override
void initState() {
super.initState();
_overlayEntries = [];
}
@override
Widget build(BuildContext context) {
return Stack(
children: <Widget>[
DrawOnImage(
key: _drawImageKey,
image: NetworkImage('https://via.placeholder.com/600x400'),
initialDrawCommands: [
DrawCommand(
type: DrawCommandType.text,
points: [Offset(50, 50)],
data: TextStyleData(
text: 'Hello Flutter!',
style: TextStyle(color: Colors.black, fontSize: 24),
),
),
DrawCommand(
type: DrawCommandType.line,
points: [Offset(50, 100), Offset(200, 100)],
data: PaintData(
color: Colors.red,
strokeWidth: 4.0,
),
),
],
onLoad: (BuildContext context, ImageProvider imageProvider) async {
// 在图像加载完成后可以执行的操作
},
onCommandAdded: (DrawCommand command) {
// 当新命令被添加时执行的操作
setState(() {
_overlayEntries.add(command.toOverlayEntry());
});
},
),
// 显示所有 OverlayEntry
if (_overlayEntries.isNotEmpty)
Positioned.fill(
child: Stack(
children: List.generate(
_overlayEntries.length,
(index) => _overlayEntries[index],
),
),
),
],
);
}
@override
void dispose() {
_overlayEntries.forEach((entry) => entry.remove());
super.dispose();
}
}
在这个示例中,我们做了以下事情:
- 导入必要的包:我们导入了
flutter/material.dart
和draw_on_image/draw_on_image.dart
。 - 定义主应用:
MyApp
是我们的主应用,它包含一个Scaffold
和一个DrawOnImageExample
组件。 - 创建绘制图像的组件:
DrawOnImageExample
是一个有状态的组件,它包含了DrawOnImage
小部件。 - 初始化绘制命令:在
DrawOnImage
小部件中,我们定义了初始的绘制命令,包括一个文本命令和一条线命令。 - 处理命令添加:当新的绘制命令被添加时,我们将它们转换为
OverlayEntry
并显示在图像上。 - 清理资源:在
dispose
方法中,我们移除所有的OverlayEntry
以避免内存泄漏。
请注意,这个示例假设 draw_on_image
插件提供了 DrawOnImage
、DrawCommand
、DrawCommandType
、TextStyleData
和 PaintData
等类和方法。实际使用时,你可能需要根据插件的具体 API 文档进行调整。如果插件的 API 有变化,请参考最新的官方文档。