Files
App.K12.Student.Miniapp_Flu…/lib/features/recite/widgets/recite_circle_progress.dart
T
崔宝新 27eba92315 feat(recite): 完成背诵模块基础框架与核心页面开发
本次提交实现了背诵模块的完整基础链路:
1. 新增词书、背单词接口层与对应数据模型
2. 完成背诵首页、章节列表页等核心页面开发
3. 实现音频播放、加载弹窗等通用组件
4. 配置路由跳转链路,替换旧版缓存传参方案
5. 对齐Vue端业务逻辑与UI样式
2026-09-11 14:38:47 +08:00

109 lines
2.9 KiB
Dart
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
import 'dart:math' as math;
import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
/// ============================================================
/// 【ReciteCircleProgress】圆环进度 —— 对标 Vue l-circle(canvas)
///
/// 用在:
/// 1. 章节页右上角「总进度」(顺时针,绿色 #1BC26E,底 #EBEBEB)
/// 2. 学习小结正确率(Vue :clockwise="false",逆时针绘制,视觉对称)
///
/// percent:0~100;中间内容由 child 自定义。
/// ============================================================
class ReciteCircleProgress extends StatelessWidget {
const ReciteCircleProgress({
super.key,
required this.percent,
required this.size,
this.strokeWidth = 4,
this.color = const Color(0xFF1BC26E),
this.trailColor = const Color(0xFFEBEBEB),
this.clockwise = true,
this.child,
});
final double percent;
final double size; // 直径
final double strokeWidth;
final Color color;
final Color trailColor;
/// false = 逆时针起笔(对标 l-circle :clockwise="false")
final bool clockwise;
final Widget? child;
@override
Widget build(BuildContext context) {
return SizedBox(
width: size.w,
height: size.w,
child: CustomPaint(
painter: _CirclePainter(
percent: percent.clamp(0, 100).toDouble(),
strokeWidth: strokeWidth.w,
color: color,
trailColor: trailColor,
clockwise: clockwise,
),
child: Center(child: child),
),
);
}
}
class _CirclePainter extends CustomPainter {
_CirclePainter({
required this.percent,
required this.strokeWidth,
required this.color,
required this.trailColor,
required this.clockwise,
});
final double percent;
final double strokeWidth;
final Color color;
final Color trailColor;
final bool clockwise;
@override
void paint(Canvas canvas, Size size) {
final center = Offset(size.width / 2, size.height / 2);
final radius = (size.width - strokeWidth) / 2;
final trackPaint =
Paint()
..style = PaintingStyle.stroke
..strokeWidth = strokeWidth
..color = trailColor;
final progressPaint =
Paint()
..style = PaintingStyle.stroke
..strokeWidth = strokeWidth
..strokeCap = StrokeCap.round
..color = color;
canvas.drawCircle(center, radius, trackPaint);
const start = -math.pi / 2; // 12 点方向
final sweep = 2 * math.pi * percent / 100;
canvas.drawArc(
Rect.fromCircle(center: center, radius: radius),
clockwise ? start : start - sweep,
sweep,
false,
progressPaint,
);
}
@override
bool shouldRepaint(covariant _CirclePainter old) =>
old.percent != percent ||
old.strokeWidth != strokeWidth ||
old.color != color ||
old.clockwise != clockwise;
}