Flutter绘图功能插件canvas的使用
Flutter绘图功能插件canvas的使用
Canvas 是一个 Flutter 包,提供了类似于 Canva 的编辑工具包。
特性
- ✅ 拖动和调整小部件大小
- ✅ 旋转小部件
- ✅ 翻转小部件
- ✅ 分组小部件
注意事项
Canvas 目前仍在开发中,还有一些功能尚未实现:
- ❌ 对象吸附
- ❌ 对象重新父级化
- ❌ 布局(类似于 Figma 中的自动布局)
- ❌ 撤销/重做
- ❌ 视口平移缩放
以下是一个完整的示例代码,展示如何在 Flutter 中使用 canvas
插件来实现基本的绘图功能。
示例代码
import 'dart:math';
import 'package:canvas/canvas.dart';
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
void main() {
runApp(MaterialApp(
home: Scaffold(
body: _ForceUpdate(
child: CanvasExample(),
),
),
));
}
class _ForceUpdate extends StatelessWidget {
final Widget child;
const _ForceUpdate({super.key, required this.child});
[@override](/user/override)
Widget build(BuildContext context) {
return KeyedSubtree(
key: UniqueKey(),
child: child,
);
}
}
class CanvasExample extends StatefulWidget {
const CanvasExample({super.key});
[@override](/user/override)
State<CanvasExample> createState() => _CanvasExampleState();
}
// 辅助函数:角度与弧度转换
double _degToRad(double deg) => deg * (pi / 180);
double _radToDeg(double rad) => rad * (180 / pi);
class _CanvasExampleState extends State<CanvasExample>
with SingleTickerProviderStateMixin {
late CanvasController _controller;
[@override](/user/override)
void initState() {
super.initState();
_controller = CanvasController(
children: [
// 第一个红色方块
BoxCanvasItem(
debugLabel: 'Red',
decoration: GestureDetector(
onTap: () {
print('Red tapped');
},
child: Container(
color: Colors.red,
child: Center(
child: Text('Red'),
),
),
),
layout: AbsoluteLayout(
offset: Offset.zero,
size: Size(100, 100),
scale: Offset(2, 2),
rotation: _degToRad(0),
),
children: [
// 红色方块内的绿色方块
BoxCanvasItem(
debugLabel: 'Green',
decoration: GestureDetector(
onTap: () {
print('Green tapped');
},
child: Container(
color: Colors.green,
child: Center(
child: Text('Green'),
),
),
),
children: [
// 绿色方块内的橙色方块
BoxCanvasItem(
debugLabel: 'Orange',
decoration: GestureDetector(
onTap: () {
print('Orange tapped');
},
child: Container(
color: Colors.orange,
child: Center(
child: Text('Orange'),
),
),
),
layout: AbsoluteLayout(
offset: Offset(50, 50),
size: Size(50, 50),
rotation: _degToRad(25),
),
),
],
layout: AbsoluteLayout(
offset: Offset(100, 100),
size: Size(50, 50),
rotation: _degToRad(44),
),
),
]),
// 第二个紫色方块
BoxCanvasItem(
debugLabel: 'Purple',
decoration: GestureDetector(
onTap: () {
print('Purple tapped');
},
child: Container(
color: Colors.purple,
child: Center(
child: Text('Purple'),
),
),
),
layout: AbsoluteLayout(
offset: Offset(200, 0),
size: Size(100, 100),
scale: Offset(1, 1),
rotation: _degToRad(25),
),
children: [
// 紫色方块内的黄色方块
BoxCanvasItem(
debugLabel: 'Yellow',
decoration: GestureDetector(
onTap: () {
print('Yellow tapped');
},
child: Container(
color: Colors.yellow,
child: Center(
child: Text('Yellow'),
),
),
),
children: [
// 黄色方块内的蓝色方块
BoxCanvasItem(
debugLabel: 'Blue',
decoration: GestureDetector(
onTap: () {
print('Blue tapped');
},
child: Container(
color: Colors.blue,
child: Center(
child: Text('Blue'),
),
),
),
layout: AbsoluteLayout(
offset: Offset(50, 50),
size: Size(50, 50),
),
),
],
layout: AbsoluteLayout(
offset: Offset(100, 100),
size: Size(50, 50),
scale: Offset(2, 2),
),
),
],
),
],
);
}
bool _shiftDown = false; // 使用 Shift 键
bool _altDown = false; // 使用 Alt 键
bool _ctrlDown = false; // 使用 Ctrl 键
FocusNode _focusNode = FocusNode();
[@override](/user/override)
Widget build(BuildContext context) {
return Focus(
focusNode: _focusNode,
onKeyEvent: (node, event) {
if (event.logicalKey == LogicalKeyboardKey.shiftLeft ||
event.logicalKey == LogicalKeyboardKey.shiftRight) {
if (event is KeyDownEvent) {
setState(() {
_shiftDown = true;
});
} else if (event is KeyUpEvent) {
setState(() {
_shiftDown = false;
});
}
return KeyEventResult.handled;
}
if (event.logicalKey == LogicalKeyboardKey.altLeft ||
event.logicalKey == LogicalKeyboardKey.altRight) {
if (event is KeyDownEvent) {
setState(() {
_altDown = true;
});
} else if (event is KeyUpEvent) {
setState(() {
_altDown = false;
});
}
return KeyEventResult.handled;
}
if (event.logicalKey == LogicalKeyboardKey.controlLeft ||
event.logicalKey == LogicalKeyboardKey.controlRight) {
if (event is KeyDownEvent) {
setState(() {
_ctrlDown = true;
});
} else if (event is KeyUpEvent) {
setState(() {
_ctrlDown = false;
});
}
return KeyEventResult.handled;
}
return KeyEventResult.ignored;
},
child: Listener(
onPointerDown: (event) {
_focusNode.requestFocus();
},
child: CanvasViewport(
controller: _controller,
multiSelect: _shiftDown,
resizeMode: ResizeMode.scale,
proportionalResize: _altDown,
symmetricResize: _ctrlDown,
anchoredRotate: _altDown,
),
),
);
}
}
更多关于Flutter绘图功能插件canvas的使用的实战教程也可以访问 https://www.itying.com/category-92-b0.html
更多关于Flutter绘图功能插件canvas的使用的实战系列教程也可以访问 https://www.itying.com/category-92-b0.html
在Flutter中,CustomPaint
和 Canvas
是用于自定义绘图的强大工具。CustomPaint
是一个 widget,它允许你使用 Canvas
来绘制自定义图形、文本、图像等。Canvas
提供了丰富的 API 来绘制各种形状、路径、文本和图像。
基本使用步骤
-
创建
CustomPaint
widget:CustomPaint
是一个 widget,它需要一个painter
参数,该参数是一个CustomPainter
对象。 -
实现
CustomPainter
:CustomPainter
是一个抽象类,你需要实现paint
和shouldRepaint
方法。paint
方法用于实际的绘图操作,shouldRepaint
方法用于决定是否需要重新绘制。 -
使用
Canvas
进行绘图: 在paint
方法中,你可以使用Canvas
对象来绘制各种图形。
示例代码
以下是一个简单的示例,展示如何使用 CustomPaint
和 Canvas
来绘制一个矩形和圆形。
import 'package:flutter/material.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text('Flutter Canvas Example')),
body: Center(
child: CustomPaint(
size: Size(300, 300),
painter: MyPainter(),
),
),
),
);
}
}
class MyPainter extends CustomPainter {
@override
void paint(Canvas canvas, Size size) {
// 绘制一个矩形
final rect = Rect.fromLTWH(50, 50, 200, 100);
final paint = Paint()
..color = Colors.blue
..style = PaintingStyle.fill;
canvas.drawRect(rect, paint);
// 绘制一个圆形
final center = Offset(size.width / 2, size.height / 2);
final radius = 50.0;
final circlePaint = Paint()
..color = Colors.red
..style = PaintingStyle.fill;
canvas.drawCircle(center, radius, circlePaint);
}
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return false;
}
}
解释
-
CustomPaint
:size
参数指定了绘图区域的大小。painter
参数指定了自定义的CustomPainter
对象。
-
MyPainter
:paint
方法中,我们使用Canvas
对象来绘制一个矩形和一个圆形。shouldRepaint
方法返回false
,表示不需要重新绘制。
-
Canvas
绘图:drawRect
方法用于绘制矩形。drawCircle
方法用于绘制圆形。Paint
对象用于设置绘图的颜色、样式等属性。
其他常用 Canvas
方法
drawLine
: 绘制一条线。drawPath
: 绘制一个路径。drawImage
: 绘制一个图像。drawText
: 绘制文本(需要使用TextPainter
)。drawArc
: 绘制一个弧形。drawOval
: 绘制一个椭圆。
使用 TextPainter
绘制文本
void paint(Canvas canvas, Size size) {
final textPainter = TextPainter(
text: TextSpan(
text: 'Hello, Flutter!',
style: TextStyle(color: Colors.black, fontSize: 24),
),
textDirection: TextDirection.ltr,
);
textPainter.layout();
textPainter.paint(canvas, Offset(50, 150));
}