app_init_page.dart 7.1 KB

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