import 'dart:async'; import 'dart:math' as math; import 'package:flutter/material.dart'; import 'package:flutter_clock/model/config.dart'; import 'package:intl/intl.dart'; class MainPage extends StatefulWidget { @override State createState() { return _MainPageState(); } } class _MainPageState extends State { final _utcMidnightRadiansOffset = radiansFromDegrees(-64); static const _secondsInDay = 86400; DateTime _localTime = DateTime.now(); @override void initState() { super.initState(); Timer.periodic(Duration(seconds: 1), (_) => setState(() => _localTime = DateTime.now())); } @override Widget build(BuildContext context) { return Scaffold( backgroundColor: Colors.white, body: SingleChildScrollView( child: Center( child: Column( children: [ Text( "Clock", style: TextStyle( fontSize: 30, color: Colors.red, ), ), Text( "author: 天问", style: TextStyle(fontFamily: Config.defaultFontFamily), ), Text( "contact: liuyuqi.gov@msn.cn", style: TextStyle(fontFamily: Config.defaultFontFamily), ), SizedBox( height: 5, ), Stack( children: [ Image.asset( 'assets/face.png', width: 350, ), Transform.rotate( angle: -(radiansFromTime(_localTime.toUtc()) + _utcMidnightRadiansOffset), child: ClipOval( clipper: InnerFaceClipper(), child: Image.asset( 'assets/face.png', width: 350, ), ), ), ], ), Text(DateFormat.EEEE().format(_localTime), style: TextStyle(fontSize: 48)), Text(DateFormat.yMMMMd().format(_localTime), style: TextStyle(fontSize: 20)), Text(DateFormat.jms().format(_localTime), style: TextStyle(fontSize: 42)), ], ), ), )); } static double radiansFromDegrees(double degrees) => degrees * math.pi / 180; static double radiansFromTime(DateTime time) { final midnightToday = DateTime(time.year, time.month, time.day); final secondsSinceMidnight = midnightToday.difference(time).inSeconds; final percent = secondsSinceMidnight / _secondsInDay; final degrees = percent * 360; return radiansFromDegrees(degrees); } } class InnerFaceClipper extends CustomClipper { final percent = 0.85; @override Rect getClip(Size size) => Rect.fromCenter( center: size.center(Offset(0, 0)), width: size.width * percent, height: size.height * percent, ); @override bool shouldReclip(CustomClipper oldClipper) => true; }