import 'package:flutter/material.dart'; /// 原理图编辑器页面 /// 核心功能:支持 1000+ 元件流畅编辑、手势操作 class SchematicEditorScreen extends StatefulWidget { final String? projectId; const SchematicEditorScreen({super.key, this.projectId}); @override State createState() => _SchematicEditorScreenState(); } class _SchematicEditorScreenState extends State { // 当前缩放级别 double _zoomLevel = 1.0; // 画布偏移 Offset _offset = Offset.zero; // 是否正在拖拽 bool _isPanning = false; // 上次触摸位置 Offset? _lastPanPosition; @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text('原理图编辑器'), actions: [ IconButton( icon: const Icon(Icons.save), onPressed: _saveProject, tooltip: '保存', ), IconButton( icon: const Icon(Icons.zoom_in), onPressed: () => _zoom(0.1), tooltip: '放大', ), IconButton( icon: const Icon(Icons.zoom_out), onPressed: () => _zoom(-0.1), tooltip: '缩小', ), IconButton( icon: const Icon(Icons.fit_screen), onPressed: _fitToScreen, tooltip: '适应屏幕', ), ], ), body: GestureDetector( // 双指缩放 onScaleStart: _handleScaleStart, onScaleUpdate: _handleScaleUpdate, onScaleEnd: _handleScaleEnd, // 单指拖拽 onPanStart: _handlePanStart, onPanUpdate: _handlePanUpdate, onPanEnd: _handlePanEnd, // 长按菜单 onLongPress: _showContextMenu, child: Container( color: const Color(0xFFFAFAFA), child: CustomPaint( size: Size.infinite, painter: SchematicCanvasPainter( zoomLevel: _zoomLevel, offset: _offset, ), ), ), ), floatingActionButton: FloatingActionButton( onPressed: _addComponent, child: const Icon(Icons.add), tooltip: '添加元件', ), ); } // 缩放处理 void _handleScaleStart(ScaleStartDetails details) { _lastPanPosition = details.focalPoint; } void _handleScaleUpdate(ScaleUpdateDetails details) { setState(() { // 更新缩放级别(限制范围) _zoomLevel = (_zoomLevel * details.scale).clamp(0.1, 10.0); // 更新偏移 if (_lastPanPosition != null) { _offset += details.focalPoint - _lastPanPosition!; } _lastPanPosition = details.focalPoint; }); } void _handleScaleEnd(ScaleEndDetails details) { _lastPanPosition = null; } // 拖拽处理 void _handlePanStart(DragStartDetails details) { _isPanning = true; _lastPanPosition = details.globalPosition; } void _handlePanUpdate(DragUpdateDetails details) { if (_isPanning && _lastPanPosition != null) { setState(() { _offset += details.delta; }); } } void _handlePanEnd(DragEndDetails details) { _isPanning = false; _lastPanPosition = null; } // 手动缩放 void _zoom(double delta) { setState(() { _zoomLevel = (_zoomLevel + delta).clamp(0.1, 10.0); }); } // 适应屏幕 void _fitToScreen() { setState(() { _zoomLevel = 1.0; _offset = Offset.zero; }); } // 显示上下文菜单 void _showContextMenu() { showModalBottomSheet( context: context, builder: (context) => SafeArea( child: Column( mainAxisSize: MainAxisSize.min, children: [ ListTile( leading: const Icon(Icons.add), title: const Text('添加元件'), onTap: () { Navigator.pop(context); _addComponent(); }, ), ListTile( leading: const Icon(Icons.content_cut), title: const Text('剪切'), onTap: () => Navigator.pop(context), ), ListTile( leading: const Icon(Icons.content_copy), title: const Text('复制'), onTap: () => Navigator.pop(context), ), ListTile( leading: const Icon(Icons.delete), title: const Text('删除'), onTap: () => Navigator.pop(context), ), ], ), ), ); } // 添加元件 void _addComponent() { // TODO: 实现元件添加逻辑 ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('添加元件功能开发中...')), ); } // 保存项目 void _saveProject() { // TODO: 实现保存逻辑 ScaffoldMessenger.of(context).showSnackBar( const SnackBar(content: Text('保存功能开发中...')), ); } } /// 原理图画布绘制器 class SchematicCanvasPainter extends CustomPainter { final double zoomLevel; final Offset offset; SchematicCanvasPainter({ required this.zoomLevel, required this.offset, }); @override void paint(Canvas canvas, Size size) { // 保存画布状态 canvas.save(); // 应用变换 canvas.translate(offset.dx, offset.dy); canvas.scale(zoomLevel); // 绘制网格 _drawGrid(canvas, size); // TODO: 绘制元件(1000+ 元件场景) // _drawComponents(canvas); // 恢复画布状态 canvas.restore(); } void _drawGrid(Canvas canvas, Size size) { final paint = Paint() ..color = const Color(0xFFE0E0E0) ..strokeWidth = 0.5; const gridSize = 50.0; // 计算可见区域 final startX = (-offset.dx / zoomLevel).clamp(-1000.0, size.width); final startY = (-offset.dy / zoomLevel).clamp(-1000.0, size.height); // 绘制垂直线 for (double x = startX; x < size.width; x += gridSize) { canvas.drawLine( Offset(x, 0), Offset(x, size.height), paint, ); } // 绘制水平线 for (double y = startY; y < size.height; y += gridSize) { canvas.drawLine( Offset(0, y), Offset(size.width, y), paint, ); } } @override bool shouldRepaint(SchematicCanvasPainter oldDelegate) { return oldDelegate.zoomLevel != zoomLevel || oldDelegate.offset != offset; } }