Flutter Canvas多画笔尺寸绘制:如何避免修改画笔影响已有线条粗细
解决Flutter Canvas切换画笔尺寸不影响已绘制线条的问题
问题根源在于你当前只存储了绘制的点坐标,所有线条都使用同一个全局的画笔宽度重绘,切换尺寸后自然全部跟着变。要解决这个问题,需要把每一段独立的绘制路径(从按下到抬起的一笔)和对应的画笔尺寸绑定存储,让每一笔都保留自己的宽度。
以下是修改后的完整代码:
import 'package:flutter/material.dart'; void main() { runApp(const MyApp()); } class MyApp extends StatelessWidget { const MyApp({super.key}); @override Widget build(BuildContext context) { return MaterialApp( title: 'Flutter Canvas', theme: ThemeData( primarySwatch: Colors.blue, ), home: const CanvasPage(), ); } } // 新增数据类:存储单条绘制路径和对应的画笔宽度 class DrawingPath { final List<Offset> points; final double strokeWidth; DrawingPath(this.points, this.strokeWidth); } class CanvasPage extends StatefulWidget { const CanvasPage({super.key}); @override CanvasPageState createState() => CanvasPageState(); } class CanvasPageState extends State<CanvasPage> { // 存储所有已完成的绘制路径 List<DrawingPath> _drawingPaths = []; // 当前正在绘制的路径(未完成,手指还没抬起) DrawingPath? _currentPath; // 当前选中的画笔尺寸 double _currentStrokeWidth = 5.0; void _handlePointerDown(PointerEvent event) { setState(() { // 按下时创建新的当前路径,使用当前选中的画笔尺寸 _currentPath = DrawingPath([event.localPosition], _currentStrokeWidth); }); } void _handlePointerMove(PointerEvent event) { if (_currentPath != null) { setState(() { // 移动时往当前路径添加新的点 _currentPath!.points.add(event.localPosition); }); } } void _handlePointerUp(PointerEvent event) { if (_currentPath != null) { setState(() { // 抬起时把当前路径加入已完成列表,清空当前路径 _drawingPaths.add(_currentPath!); _currentPath = null; }); } } void _changeStrokeWidth(double value) { setState(() { _currentStrokeWidth = value; }); } @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('Canvas'), ), body: Listener( onPointerDown: _handlePointerDown, onPointerMove: _handlePointerMove, onPointerUp: _handlePointerUp, child: CustomPaint( painter: CanvasPainter(_drawingPaths, _currentPath), size: Size.infinite, ), ), bottomNavigationBar: BottomAppBar( child: Row( mainAxisAlignment: MainAxisAlignment.spaceEvenly, children: [ IconButton( icon: const Icon(Icons.brush), onPressed: () => _changeStrokeWidth(5.0), ), IconButton( icon: const Icon(Icons.brush), onPressed: () => _changeStrokeWidth(10.0), ), IconButton( icon: const Icon(Icons.brush), onPressed: () => _changeStrokeWidth(15.0), ), ], ), ), ); } } class CanvasPainter extends CustomPainter { final List<DrawingPath> completedPaths; final DrawingPath? currentPath; CanvasPainter(this.completedPaths, this.currentPath); @override void paint(Canvas canvas, Size size) { // 先绘制所有已完成的路径,每个路径用自己的画笔宽度 for (final path in completedPaths) { final paint = Paint() ..color = Colors.blue ..strokeCap = StrokeCap.round ..strokeWidth = path.strokeWidth; for (int i = 0; i < path.points.length - 1; i++) { canvas.drawLine(path.points[i], path.points[i + 1], paint); } } // 再绘制当前正在进行的路径(手指未抬起时) if (currentPath != null) { final paint = Paint() ..color = Colors.blue ..strokeCap = StrokeCap.round ..strokeWidth = currentPath!.strokeWidth; for (int i = 0; i < currentPath!.points.length - 1; i++) { canvas.drawLine(currentPath!.points[i], currentPath!.points[i + 1], paint); } } } @override bool shouldRepaint(CanvasPainter oldDelegate) { return oldDelegate.completedPaths != completedPaths || oldDelegate.currentPath != currentPath; } }
关键改动说明:
- 新增
DrawingPath类:把每一笔的点集合和对应的画笔宽度绑定,确保每一笔都有自己的独立配置。 - 拆分存储结构:用
_drawingPaths存储所有已完成的绘制,_currentPath记录正在画的内容,避免全局变量影响所有线条。 - 修改指针事件逻辑:按下时初始化带当前宽度的路径,移动时追加点,抬起时把路径存入完成列表。
- 重写画笔绘制逻辑:遍历每个
DrawingPath,用各自的strokeWidth创建画笔,确保每一笔用自己的宽度绘制。
内容的提问来源于stack exchange,提问作者ocean
相关产品推荐
相关产品推荐

