1. 首页数据不刷新 — JournalRepository 添加 onJournalChanged Stream 变更通知,HomeBloc 订阅后自动刷新 2. 画笔再次点击不弹出面板 — 添加 ToolReactivated 事件, 工具栏检测已激活工具时发出重新激活信号 3. 钢笔铅笔效果一样 — 调整 perfect_freehand 参数 (pen: size 10/smooth 0.65, pencil: size 3/smooth 0.35) 4. 橡皮擦不生效 — ActiveStrokePainter 橡皮擦模式绘制 半透明灰色反馈,笔画完成后 setState 触发 Layer 1 重绘 5. 贴纸文字无法缩放 — DraggableElement 用 Scale 手势 替换 Pan 手势,支持双指缩放和旋转
83 lines
2.3 KiB
Dart
83 lines
2.3 KiB
Dart
// 当前笔画实时 Painter — 绘制正在绘制中的笔画
|
||
//
|
||
// 接收可变点缓冲区的直接引用 + 版本号驱动重绘。
|
||
// 每帧仅计算当前笔画的轮廓路径,不影响已完成笔画层。
|
||
// isComplete: false 让 perfect_freehand 对实时笔尖做端点平滑。
|
||
|
||
import 'package:flutter/widgets.dart';
|
||
|
||
import 'stroke_model.dart';
|
||
import 'stroke_renderer.dart';
|
||
|
||
/// 当前笔画实时 Painter
|
||
///
|
||
/// 由 ListenableBuilder 包裹,监听 ValueNotifier<int> _strokeVersion。
|
||
/// 每次 pointer move 递增 version,触发此 Painter 重绘。
|
||
/// 仅渲染当前正在绘制的笔画,已完成笔画由 CachedStrokesPainter 处理。
|
||
class ActiveStrokePainter extends CustomPainter {
|
||
/// 当前笔画的采样点(直接引用可变缓冲区,不拷贝)
|
||
final List<StrokePoint> points;
|
||
|
||
/// 画笔类型
|
||
final BrushType brushType;
|
||
|
||
/// 画笔颜色(CSS 十六进制)
|
||
final String color;
|
||
|
||
/// 画笔宽度
|
||
final double width;
|
||
|
||
/// 版本号,每次 pointer move 递增
|
||
final int version;
|
||
|
||
ActiveStrokePainter({
|
||
required this.points,
|
||
required this.brushType,
|
||
required this.color,
|
||
required this.width,
|
||
required this.version,
|
||
});
|
||
|
||
@override
|
||
void paint(Canvas canvas, Size size) {
|
||
if (points.length < 2) return;
|
||
|
||
// isComplete: false — 实时笔尖不做端点封口,视觉更自然
|
||
final outlinePoints = pointsToOutline(
|
||
points,
|
||
brushType,
|
||
width,
|
||
isComplete: false,
|
||
);
|
||
if (outlinePoints.isEmpty) return;
|
||
|
||
final path = buildStrokePath(outlinePoints);
|
||
|
||
// 橡皮擦实时反馈:绘制半透明灰色,让用户看到擦除范围
|
||
// 实际擦除在笔画完成后的合成图中通过 BlendMode.dstOut 执行
|
||
if (brushType == BrushType.eraser) {
|
||
canvas.drawPath(path, Paint()
|
||
..color = const Color(0x40808080) // 25% 灰色
|
||
..style = PaintingStyle.fill
|
||
..isAntiAlias = true);
|
||
return;
|
||
}
|
||
|
||
// 构造临时 Stroke 用于获取 Paint
|
||
final stroke = Stroke(
|
||
id: '__active__',
|
||
points: points,
|
||
brushType: brushType,
|
||
color: color,
|
||
width: width,
|
||
);
|
||
final paint = createPaintForStroke(stroke);
|
||
canvas.drawPath(path, paint);
|
||
}
|
||
|
||
@override
|
||
bool shouldRepaint(covariant ActiveStrokePainter oldDelegate) {
|
||
return oldDelegate.version != version;
|
||
}
|
||
}
|