feat(homework_review): 优化批注绘制与坐标换算,提升交互流畅度

- 批注绘制改为 Path 聚合一次性绘制
- 移除高频 print,开启 CustomPaint isComplex/willChange
- 无变换时跳过逆矩阵
- 回滚不必要的 RepaintBoundary/低过滤
- 调整 Path 判空判断写法
This commit is contained in:
DESKTOP-I3JPKHK\wy 2025-09-29 17:22:54 +08:00
parent 1fc54d7526
commit c7afafc3aa
1 changed files with 51 additions and 14 deletions

View File

@ -518,7 +518,7 @@ class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar
if (activePointers.value > 0) {
activePointers.value = activePointers.value - 1;
}
print("---进入onPointerUp ${activePointers.value}");
//
timerRef.value?.cancel();
if (!annotationState.pen.value) return;
@ -526,7 +526,7 @@ class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar
sateData.handwritings = vnHandWritings.value; //
},
onPointerMove: (PointerMoveEvent event) {
print("进入onPointerMove ${activePointers.value}");
//
if (activePointers.value != 1) return;
startTimerForHandwriting(vnHandWritings);
if (!annotationState.pen.value) return;
@ -555,9 +555,24 @@ class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar
// (dy / theScale) - (max(0, imageHeightOffsetStart) / theScale) + ((sateData.zoomOffset?.dy.abs() ?? 0) / theScale),
// ->
final inv = Matrix4.inverted(matrix);
final v = inv.transform3(Vector3(localPosition.dx, localPosition.dy, 0));
localPosition = Offset(v.x, v.y);
// final inv = Matrix4.inverted(matrix);
// final v = inv.transform3(Vector3(localPosition.dx, localPosition.dy, 0));
// localPosition = Offset(v.x, v.y);
/// -> /
/// Matrix4 4x4
/// storage[12] x storage[13] y storage[14] z
/// Matrix4 index = col * 4 + row 4 3 121314
/// theScale == 1.0 && storage[12] == 0.0 && storage[13] == 0.0 /
final double tx = matrix.storage[12];
final double ty = matrix.storage[13];
if (theScale == 1.0 && tx == 0.0 && ty == 0.0) {
// identity
} else {
final inv = Matrix4.inverted(matrix);
final v = inv.transform3(Vector3(localPosition.dx, localPosition.dy, 0));
localPosition = Offset(v.x, v.y);
}
// 0..maxWidth0..actualHeight
if (localPosition.dy < 0 || localPosition.dy > actualHeight) return;
@ -625,7 +640,8 @@ class QuestionImageView extends HookWidget with EventBusMixin<BottomOperationBar
RepaintBoundary(
key: logic.pictureOverviewKey,
child: CustomPaint(
// isComplex: true,
isComplex: true,
willChange: true,
size: Size(maxWidth, actualHeight),
foregroundPainter: DrawingPainter(ctrl: vnHandWritings),
// child: $TheCachedNetworkImage(
@ -658,19 +674,40 @@ class DrawingPainter extends CustomPainter {
final Paint paintBrush = Paint()
..color = Colors.red
..strokeCap = StrokeCap.round
..strokeWidth = 0.7.sp;
..strokeJoin = StrokeJoin.round
..isAntiAlias = true
..strokeWidth = 0.7.sp
..style = PaintingStyle.stroke;
DrawingPainter({required this.ctrl}) : super(repaint: ctrl);
@override
void paint(Canvas canvas, Size size) {
var points = ctrl.value;
var pointsLength = points.length;
for (int i = 0; i < pointsLength; i++) {
Offset? offsetData = points[i];
Offset? nextOffsetData = pointsLength - 1 == i ? null : points[i + 1];
if (offsetData != null && nextOffsetData != null) {
canvas.drawLine(offsetData, nextOffsetData, paintBrush);
final List<dynamic> points = ctrl.value;
if (points.isEmpty) return;
Path path = Path();
Offset? previous;
for (int i = 0; i < points.length; i++) {
final Offset? current = points[i] as Offset?;
if (current == null) {
//
if (path.computeMetrics().isNotEmpty) {
canvas.drawPath(path, paintBrush);
}
path = Path();
previous = null;
continue;
}
if (previous == null) {
path.moveTo(current.dx, current.dy);
} else {
path.lineTo(current.dx, current.dy);
}
previous = current;
}
//
if (path.computeMetrics().isNotEmpty) {
canvas.drawPath(path, paintBrush);
}
}