Flutter CustomPainter的Canvas练习,画钟表

import 'dart:async';
import 'dart:math';

import 'package:flutter/material.dart';

class ClockPage extends StatelessWidget {
  const ClockPage({Key? key}) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return Clock();
  }
}

class Clock extends StatefulWidget {
  const Clock({Key? key}) : super(key: key);

  @override
  _ClockState createState() => _ClockState();
}

class _ClockState extends State<Clock> {
  // 定时器,一秒一次
  late Timer _timer;

  @override
  void initState() {
    super.initState();

    _timer = Timer.periodic(Duration(seconds: 1), (timer) {
      setState(() {});
    });
  }

  @override
  void dispose() {
    _timer.cancel();
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    // AspectRatio 可以根据具体的长宽比约束 child 的布局范围, 从而影响 child 的大小. 通常在视频、图像中会经常使用
    return AspectRatio(
      aspectRatio: 1,
      child: CustomPaint(
        painter: ClockPainter(dateTime: DateTime.now()),
      ),
    );
  }
}

class ClockPainter extends CustomPainter {
  final DateTime dateTime;

  ClockPainter({super.repaint, required this.dateTime});

  @override
  void paint(Canvas canvas, Size size) {
    final centerX = size.width / 2; // 计算画布中心点的X坐标
    final centerY = size.height / 2; // 计算画布中心点的Y坐标
    final center = Offset(centerX, centerY); // 画布中心点
    final radius = min(centerX - 10, centerY); // 计算画布的半径,取宽和高中的最小值

    final paint = Paint()
      ..strokeWidth = 10
      ..strokeCap = StrokeCap.round; // 边缘圆滑

    // 画表盘
    paint.color = Colors.black; // 设置画笔颜色为黑色
    paint.style = PaintingStyle.stroke; // 设置画笔样式为描边
    canvas.drawCircle(center, radius, paint); // 在画布上画一个圆形的表盘

    // 画刻度
    for (var i = 0; i < 60; i++) {
      // 循环画60个刻度线
      paint.strokeWidth = 5; // 刻度线的宽度
      var tickLength = 15;
      if (i % 5 == 0) {
        paint.strokeWidth = 10;
        tickLength = 30; // 如果是5的倍数,则刻度线长度大,否则短
      }
      var tickX1 = centerX + radius * cos(i * 6 * pi / 180); // 计算刻度线起点的X坐标
      var tickY1 = centerY + radius * sin(i * 6 * pi / 180); // 计算刻度线起点的Y坐标
      var tickX2 = centerX +
          (radius - tickLength) * cos(i * 6 * pi / 180); // 计算刻度线终点的X坐标
      var tickY2 = centerY +
          (radius - tickLength) * sin(i * 6 * pi / 180); // 计算刻度线终点的Y坐标
      canvas.drawLine(
          Offset(tickX1, tickY1), Offset(tickX2, tickY2), paint); // 在画布上画刻度线
    }

    int hour = dateTime.hour;
    int minute = dateTime.minute;
    int second = dateTime.second;

    // 画时针,时针:1小时30°,1分钟0.5°, 乘以 (pi / 180) 把角度转成弧度
    paint.strokeWidth = 12;
    var a = (hour * 30 + minute * 0.5) - 90;
    final hourHandX = centerX + radius * 0.4 * cos(a * pi / 180); // 计算时针的X坐标
    final hourHandY = centerY + radius * 0.4 * sin(a * pi / 180); // 计算时针的Y坐标
    paint.color = Colors.red; // 设置画笔颜色为红色
    canvas.drawLine(center, Offset(hourHandX, hourHandY), paint); // 在画布上画

    // 画分针,分针:1分钟6°,1秒钟0.1°
    paint.strokeWidth = 8;
    a = (minute * 6 + second * 0.1) - 90;
    final minuteHandX = centerX + radius * 0.6 * cos(a * pi / 180); // 计算分针的X坐标
    final minuteHandY = centerY + radius * 0.6 * sin(a * pi / 180); // 计算分针的Y坐标
    paint.color = Colors.green; // 设置画笔颜色为红色
    canvas.drawLine(center, Offset(minuteHandX, minuteHandY), paint); // 在画布上画

    // 画秒针,秒针,1秒6°
    paint.strokeWidth = 5;
    a = (second * 6) - 90;
    final secondHandX = centerX + radius * 0.8 * cos(a * pi / 180); // 计算秒针的X坐标
    final secondHandY = centerY + radius * 0.8 * sin(a * pi / 180); // 计算秒针的Y坐标
    paint.color = Colors.blue; // 设置画笔颜色为蓝色
    canvas.drawLine(center, Offset(secondHandX, secondHandY), paint); // 在画布上画

    paint.color = Colors.black;
    paint.style = PaintingStyle.fill;
    canvas.drawCircle(center, 8, paint);
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    if (dateTime != (oldDelegate as ClockPainter).dateTime) {
      return true; // 要重绘
    } else {
      return false;
    }
  }
}

效果如下:

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Flutter CanvasFlutter 框架提供的一个功能强大的绘图 API,它允许你直接在屏幕上绘制图形、文本和其他视觉元素。你可以使用 Flutter Canvas 创建自定义的 UI 控件、动效果以及图表等。 通过 Flutter Canvas,你可以使用各种绘图方法来绘制形状、路径、渐变、图片和文本等。你可以使用 Canvas 类提供的方法来绘制直线、曲线、圆形、矩形等基本形状,还可以使用 Path 类来创建复杂的路径。同时,你也可以设置笔的样式、颜色和透明度等属性,来实现各种视觉效果。 在 Flutter 中使用 Canvas,你需要在自定义的绘制方法中重写父类的 paint 方法,并将 Canvas 对象作为参数传入。然后,你可以在这个方法中使用 Canvas 对象提供的方法来绘制你想要的图形。 例如,下面是一个简单的 Flutter Canvas 绘制一个红色圆形的示例代码: ```dart import 'package:flutter/material.dart'; class MyCanvasWidget extends StatelessWidget { @override Widget build(BuildContext context) { return CustomPaint( painter: MyPainter(), ); } } class MyPainter extends CustomPainter { @override void paint(Canvas canvas, Size size) { final paint = Paint() ..color = Colors.red ..style = PaintingStyle.fill; final center = Offset(size.width / 2, size.height / 2); final radius = size.width / 4; canvas.drawCircle(center, radius, paint); } @override bool shouldRepaint(covariant CustomPainter oldDelegate) { return false; } } ``` 这段代码定义了一个自定义的绘制 Widget `MyCanvasWidget`,并在其 `paint` 方法中使用 Canvas 绘制了一个红色的圆形。在 Flutter 的 UI 树中使用 `CustomPaint` 包裹这个自定义的绘制 Widget,即可将这个绘制效果显示在屏幕上。 希望这个简单的示例可以帮助你了解 Flutter Canvas 的基本使用方法。如果你有更多关于 Flutter Canvas 的问题,欢迎继续提问!
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值