home_board.dart 2.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899
  1. import 'dart:typed_data';
  2. import 'package:flutter/material.dart';
  3. import 'package:flutter/services.dart';
  4. import 'package:image_puzzle/config/device.dart';
  5. import 'package:image_puzzle/models/download.dart';
  6. import 'package:image_puzzle/models/items.dart';
  7. import 'package:logging/logging.dart';
  8. import 'dart:ui' as ui;
  9. final Logger _log = Logger('home_board');
  10. enum HomeBoardStatus { loading, shuffle, playing, done, unlocking }
  11. class HomeBoard {
  12. final Device device;
  13. // 原合集图
  14. ui.Image? image;
  15. // 纸牌背面图
  16. late ui.Image cardImage;
  17. // board 的canvas绘制区域尺寸
  18. final double canvasWidth;
  19. final double canvasHeight;
  20. /// 一张合集分为几宫格,固定5x5
  21. final int rows = 5;
  22. final int cols = 5;
  23. // 每个piece的逻辑尺寸
  24. double get pieceLogicalWidth => canvasWidth / cols;
  25. double get pieceLogicalHeight => canvasHeight / rows;
  26. ValueNotifier boardNotifier = ValueNotifier(1);
  27. HomeBoardStatus status = HomeBoardStatus.loading;
  28. ListItem? _currentCollectionItem;
  29. ListItem? get currentCollectionItem => _currentCollectionItem;
  30. set currentCollectionItem(ListItem? item) {
  31. if (item == null) return;
  32. if (_currentCollectionItem == null || _currentCollectionItem!.id != item.id) {
  33. _currentCollectionItem = item;
  34. _loadImage();
  35. }
  36. }
  37. ValueNotifier isReadyNotifier = ValueNotifier(false);
  38. // 用于存储合集解锁动画相关信息
  39. Offset _unlockTargetOffset = Offset.zero;
  40. double _unlockTargetScale = 1.0;
  41. Offset get unlockTargetOffset => _unlockTargetOffset;
  42. double get unlockTargetScale => _unlockTargetScale;
  43. void setUnlockAnimationTarget({required Offset targetOffset, required double targetScale}) {
  44. _unlockTargetOffset = targetOffset;
  45. _unlockTargetScale = targetScale;
  46. }
  47. HomeBoard({required this.canvasWidth, required this.canvasHeight, required this.device}) {
  48. _loadCardImage();
  49. }
  50. void invalidate() {
  51. boardNotifier.value++;
  52. }
  53. // 加载合集图
  54. void _loadImage() async {
  55. double dpr = device.devicePixelRatio;
  56. ItemLoader itemLoader = ItemLoader.load(currentCollectionItem!);
  57. image = await itemLoader.getImageBySize((canvasWidth * dpr).round(), (canvasHeight * dpr).round());
  58. isReadyNotifier.value = true;
  59. invalidate();
  60. }
  61. // 加载卡片图
  62. void _loadCardImage() async {
  63. double dpr = device.devicePixelRatio;
  64. // 加载扑克背面图片,用于制作发牌动画
  65. final Size bestCardImageSize = Size(pieceLogicalWidth * dpr, pieceLogicalHeight * dpr);
  66. final ByteData cardData = await rootBundle.load('assets/images/backcard_green.png');
  67. final ui.Codec cardCodec = await ui.instantiateImageCodec(
  68. cardData.buffer.asUint8List(),
  69. targetWidth: bestCardImageSize.width.round(),
  70. targetHeight: bestCardImageSize.height.round(),
  71. );
  72. final ui.FrameInfo cardFrameInfo = await cardCodec.getNextFrame();
  73. cardImage = cardFrameInfo.image;
  74. invalidate();
  75. }
  76. }