Simply put the code directly:
import 'dart:math';
import 'package:flutter/material.dart';
class ClockPainter extends CustomPainter {
final BuildContext context;
final DateTime datetime;
// 构造函数,需要传入BuildContext和DateTime
ClockPainter(this.context, this.datetime);
@override
void paint(Canvas canvas, Size size) {
// 计算中心点的坐标
double centerX = size.width / 2;
double centerY = size.height / 2;
Offset center = Offset(centerX, centerY);
// 计算时针、分针和秒针的长度
double minHandLength = centerX * 0.75;
double hourHandLength = centerX * 0.5;
double secHandLength = centerX * 0.85;
// 创建画分针的画笔
Paint minHandPaint = Paint()
..color = Colors.orange
..style = PaintingStyle.stroke
..strokeWidth = 10;
// 计算分针的角度
double minDegrees = 360 / 60 * datetime.minute;
// 计算分针的终点坐标
double minX = centerX + minHandLength * cos(minDegrees * pi / 180);
double minY = centerY + minHandLength * sin(minDegrees * pi / 180);
// 画分针
canvas.drawLine(center, Offset(minX, minY), minHandPaint);
// 创建画时针的画笔
Paint hourHandPaint = Paint()
..color = Colors.brown
..style = PaintingStyle.stroke
..strokeWidth = 16;
// 计算时针的角度
double hourDegrees = 360 / 12 * (datetime.hour % 12) + datetime.minute / 60 * 30;
// 计算时针的终点坐标
double hourX = centerX + hourHandLength * cos(hourDegrees * pi / 180);
double hourY = centerY + hourHandLength * sin(hourDegrees * pi / 180);
// 画时针
canvas.drawLine(center, Offset(hourX, hourY), hourHandPaint);
// 创建画秒针的画笔
Paint secHandPaint = Paint()
..color = Colors.red
..style = PaintingStyle.stroke
..strokeWidth = 2;
// 计算秒针的角度
double secDegrees = 360 / 60 * datetime.second;
// 计算秒针的终点坐标
double secX = centerX + secHandLength * cos(radians(secDegrees - 90));
double secY = centerY + secHandLength * sin(radians(secDegrees - 90));
// 画秒针
canvas.drawLine(center, Offset(secX, secY), secHandPaint);
// 创建画刻度的画笔
Paint dashPaint = Paint()
..color = Colors.grey
..style = PaintingStyle.stroke
..strokeWidth = 1;
// 定义刻度的总数和长度
int totalDashes = 60;
double longDashLength = 20; // 长刻度线的长度
double shortDashLength = 10; // 短刻度线的长度
double dashSpace = size.width / 2 - longDashLength;
// 画每一个刻度
for (int i = 0; i < totalDashes; i++) {
// 计算每一个刻度的角度
double min = 360 / totalDashes * i;
// 计算每一个刻度的起点坐标
double x1 = centerX + dashSpace * cos(radians(min - 90));
double y1 = centerY + dashSpace * sin(radians(min - 90));
// 如果是整点,则刻度线长一些
double dashLength = i % 5 == 0 ? longDashLength : shortDashLength;
// 计算每一个刻度的终点坐标
double x2 = centerX + (dashSpace + dashLength) * cos(radians(min - 90));
double y2 = centerY + (dashSpace + dashLength) * sin(radians(min - 90));
// 画刻度
canvas.drawLine(Offset(x1, y1), Offset(x2, y2), dashPaint);
}
// 准备画数字
TextPainter textPainter = TextPainter(
textAlign: TextAlign.center,
textDirection: TextDirection.ltr,
);
// 画每一个数字
for (int i = 1; i <= 12; i++) {
// 设置数字的样式
textPainter.text = TextSpan(
text: '$i',
style: TextStyle(
color: Colors.black,
fontSize: 22,
),
);
// 这里我们需要让textPainter进行布局,否则我们无法获取到文字的宽度和高度
textPainter.layout();
// 计算每个数字的位置,这里我们让12个数字均匀的分布在表盘上
double angle = 2 * pi / 12 * i;
double x = centerX + (size.width / 2 - 40) * cos(angle - pi / 2) - textPainter.width / 2;
double y = centerY + (size.height / 2 - 40) * sin(angle - pi / 2) - textPainter.height / 2;
Offset offset = Offset(x, y);
// 在计算出的位置上绘制文字
textPainter.paint(canvas, offset);
}
}
// 将角度转换为弧度
double radians(double degree) {
return degree * pi / 180;
}
// 返回true表示每次都需要重绘
@override
bool shouldRepaint(CustomPainter oldDelegate) {
return true;
}
}
The comments are written very clearly, no further elaboration is needed;
Refresh the interface where used.
DateTime _now = DateTime.now();
void _getTime() {
setState(() {
_now = DateTime.now();
});
}
Initialize the timer and remember to close it when it is destroyed.
@override
void initState() {
super.initState();
_timer = Timer.periodic(Duration(seconds: 1), (Timer t) => _getTime());
}
@override
void dispose() {
_timer.cancel();
super.dispose();
}
A simple clock dial is drawn and can be expanded according to our specific needs.