import 'dart:math'; import 'dart:ui' as ui; import 'package:flutter/material.dart'; import 'package:flutter/scheduler.dart'; import 'package:flutter/services.dart'; /// create by 张风捷特烈 on 2020/11/5 /// contact me by email 1981462002@qq.com /// 说明: class Paper extends StatelessWidget { const Paper({super.key}); @override Widget build(BuildContext context) { return Container( color: Colors.white, alignment: Alignment.center, child: const ClockPanel(), ); } } class ClockManage with ChangeNotifier { late List particles; late DateTime datetime; // 时间 /// 粒子列表 int numParticles; /// 最大粒子数 Size size; // 尺寸 ClockManage({this.size= Size.zero, this.numParticles = 500}) { particles = List.filled(numParticles,Particle()); datetime = DateTime.now(); } collectParticles(DateTime datetime) { count = 0; particles.forEach((Particle element) { if(element!=null){ element.active = false; } }); collectDigit(target: datetime.hour ~/ 10, offsetRate: 0); collectDigit(target: datetime.hour % 10, offsetRate: 1); collectDigit(target: 10, offsetRate: 3.2); collectDigit(target: datetime.minute ~/ 10, offsetRate: 2.5); collectDigit(target: datetime.minute % 10, offsetRate: 3.5); collectDigit(target: 10, offsetRate: 7.25); collectDigit(target: datetime.second ~/ 10, offsetRate: 5); collectDigit(target: datetime.second % 10, offsetRate: 6); } int count = 0; double _radius = 4; void collectDigit({int target = 0, double offsetRate = 0}) { if (target > 10 && count > numParticles) { return; } double space = _radius * 2; double offSetX = (digits[target][0].length * 2 * (_radius + 1) + space) * offsetRate; for (int i = 0; i < digits[target].length; i++) { for (int j = 0; j < digits[target][j].length; j++) { if (digits[target][i][j] == 1) { double rX = j * 2 * (_radius + 1) + (_radius + 1); //第(i,j)个点圆心横坐标 double rY = i * 2 * (_radius + 1) + (_radius + 1); //第(i,j)个点圆心纵坐标 particles[count] = Particle(x: rX + offSetX, y: rY, size: _radius, color: Colors.blue, active: true); count++; } } } } void tick(DateTime now) { collectParticles(now); notifyListeners(); } void doUpdate(Particle p, DateTime datetime) { } } class ClockPainter extends CustomPainter { final ClockManage manage; ClockPainter({ required this.manage}) : super(repaint: manage); Paint clockPaint = Paint(); @override void paint(Canvas canvas, Size size) { manage.particles.where((e) => e!=null&&e.active).forEach((particle) { clockPaint..color = particle.color; canvas.drawCircle( Offset(particle.x, particle.y), particle.size, clockPaint); }); } @override bool shouldRepaint(covariant CustomPainter oldDelegate) => false; } class ClockPanel extends StatefulWidget { const ClockPanel({super.key}); @override _ClockPanelState createState() => _ClockPanelState(); } class _ClockPanelState extends State with SingleTickerProviderStateMixin { late Ticker _ticker; late ClockManage pm; @override void initState() { super.initState(); pm = ClockManage(size: Size(550, 200)); _ticker = createTicker(_tick) ..start(); } @override void dispose() { _ticker.dispose(); super.dispose(); } @override Widget build(BuildContext context) { return CustomPaint( size: pm.size, painter: ClockPainter(manage: pm), ); } void _tick(Duration duration) { DateTime now = DateTime.now(); if (now.millisecondsSinceEpoch - pm.datetime.millisecondsSinceEpoch > 1000) { pm..datetime = now..tick(now); } } } class Particle { /// x 位移. double x; /// y 位移. double y; /// 粒子大小. double size; /// 粒子颜色. Color color; bool active; // 粒子是否可用 double vx; /// 粒子水平速度. double ax; // 粒子水平加速度 double ay; // 粒子竖直加速度 double vy; ///粒子竖直速度. Particle({ this.x = 0, this.y = 0, this.size = 0, this.vx=0, this.ax=0, this.ay=0, this.vy=0, this.active = true, this.color = Colors.black, }); } const colors = [ Color(0x8833B5E5), Color(0x880099CC), Color(0x889933CC), Color(0x8899CC00), Color(0x88669900), Color(0x88FFBB33), Color(0x88FF8800), Color(0x88FF4444), Color(0x88CC0000) ]; const digits = [ [ [0, 0, 1, 1, 1, 0, 0], [0, 1, 1, 0, 1, 1, 0], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [0, 1, 1, 0, 1, 1, 0], [0, 0, 1, 1, 1, 0, 0] ], //0 [ [0, 0, 0, 1, 1, 0, 0], [0, 1, 1, 1, 1, 0, 0], [0, 0, 0, 1, 1, 0, 0], [0, 0, 0, 1, 1, 0, 0], [0, 0, 0, 1, 1, 0, 0], [0, 0, 0, 1, 1, 0, 0], [0, 0, 0, 1, 1, 0, 0], [0, 0, 0, 1, 1, 0, 0], [0, 0, 0, 1, 1, 0, 0], [1, 1, 1, 1, 1, 1, 1] ], //1 [ [0, 1, 1, 1, 1, 1, 0], [1, 1, 0, 0, 0, 1, 1], [0, 0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 1, 1, 0], [0, 0, 0, 1, 1, 0, 0], [0, 0, 1, 1, 0, 0, 0], [0, 1, 1, 0, 0, 0, 0], [1, 1, 0, 0, 0, 0, 0], [1, 1, 0, 0, 0, 1, 1], [1, 1, 1, 1, 1, 1, 1] ], //2 [ [1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 1, 1, 0], [0, 0, 0, 1, 1, 0, 0], [0, 0, 1, 1, 1, 0, 0], [0, 0, 0, 0, 1, 1, 0], [0, 0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [0, 1, 1, 1, 1, 1, 0] ], //3 [ [0, 0, 0, 0, 1, 1, 0], [0, 0, 0, 1, 1, 1, 0], [0, 0, 1, 1, 1, 1, 0], [0, 1, 1, 0, 1, 1, 0], [1, 1, 0, 0, 1, 1, 0], [1, 1, 1, 1, 1, 1, 1], [0, 0, 0, 0, 1, 1, 0], [0, 0, 0, 0, 1, 1, 0], [0, 0, 0, 0, 1, 1, 0], [0, 0, 0, 1, 1, 1, 1] ], //4 [ [1, 1, 1, 1, 1, 1, 1], [1, 1, 0, 0, 0, 0, 0], [1, 1, 0, 0, 0, 0, 0], [1, 1, 1, 1, 1, 1, 0], [0, 0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [0, 1, 1, 1, 1, 1, 0] ], //5 [ [0, 0, 0, 0, 1, 1, 0], [0, 0, 1, 1, 0, 0, 0], [0, 1, 1, 0, 0, 0, 0], [1, 1, 0, 0, 0, 0, 0], [1, 1, 0, 1, 1, 1, 0], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [0, 1, 1, 1, 1, 1, 0] ], //6 [ [1, 1, 1, 1, 1, 1, 1], [1, 1, 0, 0, 0, 1, 1], [0, 0, 0, 0, 1, 1, 0], [0, 0, 0, 0, 1, 1, 0], [0, 0, 0, 1, 1, 0, 0], [0, 0, 0, 1, 1, 0, 0], [0, 0, 1, 1, 0, 0, 0], [0, 0, 1, 1, 0, 0, 0], [0, 0, 1, 1, 0, 0, 0], [0, 0, 1, 1, 0, 0, 0] ], //7 [ [0, 1, 1, 1, 1, 1, 0], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [0, 1, 1, 1, 1, 1, 0], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [0, 1, 1, 1, 1, 1, 0] ], //8 [ [0, 1, 1, 1, 1, 1, 0], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [1, 1, 0, 0, 0, 1, 1], [0, 1, 1, 1, 0, 1, 1], [0, 0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 0, 1, 1], [0, 0, 0, 0, 1, 1, 0], [0, 0, 0, 1, 1, 0, 0], [0, 1, 1, 0, 0, 0, 0] ], //9 [ [0, 0, 0, 0], [0, 0, 0, 0], [0, 1, 1, 0], [0, 1, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0], [0, 1, 1, 0], [0, 1, 1, 0], [0, 0, 0, 0], [0, 0, 0, 0] ] //: ];