Drawing of custom clock interface of flutter custom series

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();
}

picture.png

A simple clock dial is drawn and can be expanded according to our specific needs.

Guess you like

Origin blog.csdn.net/qq_28563283/article/details/131241054