app_init_page.dart 7.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245
  1. import 'package:get/get.dart';
  2. import 'package:flutter/material.dart';
  3. import 'package:trackoffical_app/generated/assets.dart';
  4. import 'package:trackoffical_app/logger.dart';
  5. import 'package:trackoffical_app/screen.dart';
  6. import 'package:trackoffical_app/service/all_init.dart';
  7. import 'package:trackoffical_app/service/app.dart';
  8. import 'package:trackoffical_app/utils.dart';
  9. import 'package:rive/rive.dart';
  10. import 'package:vector_math/vector_math.dart' as vec;
  11. final _duration = 2.seconds;
  12. class AppInitPageController extends GetxController {
  13. @override
  14. void onReady() async {
  15. final initFuture = initAllServicesAndThenCallback();
  16. final minWaitFuture = _duration.delay();
  17. final l = await Future.wait([initFuture, minWaitFuture]);
  18. final firstPage = l[0];
  19. firstPage();
  20. }
  21. void setScreenInfo(BuildContext context) {
  22. var msg = '获取屏幕信息\n';
  23. msg += 'width: ${context.width}, height: ${context.height}\n';
  24. var pixelRatio = context.devicePixelRatio;
  25. msg += 'pixelRatio: $pixelRatio\n';
  26. App.to.devicePixelRatio = pixelRatio;
  27. App.to.screenSize = Size(context.width, context.height);
  28. SizeFit.screenInit(context);
  29. debug(msg);
  30. }
  31. }
  32. class AppInitPage extends GetView<AppInitPageController> {
  33. const AppInitPage({super.key});
  34. static Bindings bindings() {
  35. return BindingsBuilder(() {
  36. Get.put<AppInitPageController>(AppInitPageController());
  37. });
  38. }
  39. @override
  40. Widget build(BuildContext context) {
  41. controller.setScreenInfo(context);
  42. return const AnimationPage();
  43. }
  44. }
  45. class AnimationPage extends StatefulWidget {
  46. const AnimationPage({super.key});
  47. @override
  48. State<StatefulWidget> createState() {
  49. return _AnimationPageState();
  50. }
  51. }
  52. class _AnimationPageState extends State<AnimationPage>
  53. with SingleTickerProviderStateMixin {
  54. late Animation<double> animation;
  55. late AnimationController controller;
  56. @override
  57. void initState() {
  58. super.initState();
  59. controller = AnimationController(duration: _duration, vsync: this);
  60. animation = Tween<double>(begin: 0, end: 1).animate(controller);
  61. controller.forward();
  62. }
  63. @override
  64. void dispose() {
  65. controller.dispose();
  66. super.dispose();
  67. }
  68. @override
  69. Widget build(BuildContext context) {
  70. SizeFit.screenInit(context);
  71. return Scaffold(
  72. body: Container(
  73. decoration: const BoxDecoration(
  74. image: DecorationImage(
  75. image: AssetImage(Assets.imagesBkAppInit), fit: BoxFit.cover)),
  76. child: Column(
  77. children: [
  78. Expanded(
  79. flex: 1,
  80. child: Container(
  81. // color: const Color(0xffffcb00),
  82. alignment: Alignment.bottomCenter,
  83. child: Stack(
  84. alignment: Alignment.center,
  85. children: [
  86. Image.asset(
  87. Assets.imagesImCompassNoMap,
  88. height: 25.3.wp,
  89. fit: BoxFit.fitHeight,
  90. ),
  91. // AnimatedCompass(animation: animation),
  92. SizedBox(
  93. height: 18.0.wp,
  94. child: const RiveAnimation.asset(
  95. 'assets/images/am_app_start_arrow.riv',
  96. fit: BoxFit.fitHeight,
  97. ))
  98. ],
  99. ),
  100. )),
  101. Expanded(
  102. flex: 1,
  103. child: Column(
  104. children: [
  105. AnimatedText(animation: animation),
  106. Expanded(
  107. child: Stack(
  108. alignment: Alignment.center,
  109. children: [
  110. Center(
  111. child: AnimatedColors(
  112. animation: animation,
  113. ),
  114. ),
  115. Positioned(
  116. bottom: 2.6.wp,
  117. child:
  118. Image.asset(Assets.imagesIcLogo, height: 5.0.wp))
  119. ],
  120. ))
  121. ],
  122. )),
  123. ],
  124. ),
  125. ),
  126. );
  127. }
  128. }
  129. class AnimatedCompass extends AnimatedWidget {
  130. const AnimatedCompass({super.key, required Animation<double> animation})
  131. : super(listenable: animation);
  132. @override
  133. Widget build(BuildContext context) {
  134. final animation = listenable as Animation<double>;
  135. return Transform.rotate(
  136. angle: vec.radians(animation.value * 360),
  137. alignment: Alignment.center,
  138. child: Image.asset(
  139. Assets.imagesImCompassArrow,
  140. height: 44.0.wp,
  141. fit: BoxFit.fitHeight,
  142. ),
  143. );
  144. }
  145. }
  146. class AnimatedText extends AnimatedWidget {
  147. const AnimatedText({super.key, required Animation<double> animation})
  148. : super(listenable: animation);
  149. @override
  150. Widget build(BuildContext context) {
  151. final animation = listenable as Animation<double>;
  152. var style = (context.textTheme.titleLarge ?? const TextStyle())
  153. .copyWith(color: Colors.white, fontSize: 3.9.wp);
  154. return Opacity(
  155. opacity: animation.value,
  156. child: Column(
  157. mainAxisSize: MainAxisSize.min,
  158. crossAxisAlignment: CrossAxisAlignment.center,
  159. children: [
  160. SizedBox(
  161. height: 3.9.wp,
  162. ),
  163. Text('确定方向 ', style: style),
  164. Text(' 发现你自己的路!', style: style.copyWith(fontSize: 3.9.wp)),
  165. Text('Orienting, Discover Your Own Way!',
  166. style: style.copyWith(
  167. color: const Color(0xffade0ff), fontSize: 2.5.wp)),
  168. ],
  169. ));
  170. }
  171. }
  172. class AnimatedColors extends AnimatedWidget {
  173. const AnimatedColors({super.key, required Animation<double> animation})
  174. : super(listenable: animation);
  175. @override
  176. Widget build(BuildContext context) {
  177. final animation = listenable as Animation<double>;
  178. var style = (context.textTheme.titleLarge ?? const TextStyle())
  179. .copyWith(color: Colors.white, fontSize: 8.33.wp);
  180. var children = <Widget>[];
  181. for (var i = 0; i < hrPColors.length; i++) {
  182. final color = hrPColors[i];
  183. var opacity = 0.0;
  184. if (i < animation.value * hrPColors.length) {
  185. opacity = 1;
  186. }
  187. children.add(Opacity(
  188. opacity: opacity,
  189. child: Container(
  190. width: 1.2.wp,
  191. decoration: BoxDecoration(
  192. color: color,
  193. borderRadius: BorderRadius.circular(2.0.wp),
  194. border: Border.all(color: Colors.white.withAlpha(100))),
  195. )));
  196. }
  197. return Column(
  198. mainAxisSize: MainAxisSize.min,
  199. crossAxisAlignment: CrossAxisAlignment.center,
  200. children: [
  201. SizedBox(
  202. width: 10.wp,
  203. height: 3.9.wp,
  204. child: Row(
  205. mainAxisAlignment: MainAxisAlignment.spaceBetween,
  206. children: children,
  207. )),
  208. SizedBox(height: 6.66.wp),
  209. // Text('支持心率带检测身体数据',
  210. // style: style.copyWith(
  211. // color: const Color(0xffffcb00), fontSize: 3.3.wp)),
  212. ],
  213. );
  214. }
  215. }
  216. void main() {
  217. runPreview(const AnimationPage());
  218. }