flutter 如何在抖动中显示较大图像的特定部分?

42fyovps  于 2023-03-19  发布在  Flutter
关注(0)|答案(1)|浏览(153)

我有一个包含多个较小图像的大图像(spritesheet)
如何显示特定的“sprite”?
我已经找到了一些答案,但它们都与游戏有关,而我的应用程序不是游戏。
这是我目前为止得到的结果,但这会引发一个错误

Failed assertion: line 535 pos 12: 'sourceSize == inputSize': centerSlice was used 
with a BoxFit that does not guarantee that the image is fully visible

我所要做的事情的全部要点是,图像不是完全可见的,而是只有一小部分。

class SpriteImage extends StatelessWidget {
  final String assetName;
  final int index;
  final int rowCount;
  final int columnCount;
  final double width;
  final double height;

  SpriteImage({
    required this.assetName,
    required this.index,
    required this.rowCount,
    required this.columnCount,
    required this.width,
    required this.height,
  });

  @override
  Widget build(BuildContext context) {
    int rowIndex = index ~/ columnCount;
    int columnIndex = index % columnCount;

    double srcX = columnIndex * width;
    double srcY = rowIndex * height;

    return Image.asset(
      assetName,
      width: width,
      height: height,
      fit: BoxFit.fill,
      alignment: Alignment.topLeft,
      // Clip the image to the desired sprite.
      repeat: ImageRepeat.noRepeat,
      scale: 1.0,
      // Define the source rectangle to crop the sprite from the sprite sheet.
      centerSlice: Rect.fromLTRB(srcX + 1, srcY + 1, srcX + width - 1, srcY + height - 1),
    );
  }
}
lskq00tm

lskq00tm1#

多亏了pskink上面的回答,我才能够创建一个解决方案:

class SpriteSheetImage extends StatelessWidget {
  final String imagePath;
  final int spriteWidth;
  final int spriteHeight;
  final int rowIndex;
  final int columnIndex;

  const SpriteSheetImage({
    Key? key,
    required this.imagePath,
    required this.spriteWidth,
    required this.spriteHeight,
    required this.rowIndex,
    required this.columnIndex,
  }) : super(key: key);

  @override
  Widget build(BuildContext context) {
    return FutureBuilder<ui.Image>(
      future: _loadImage(),
      builder: (context, snapshot) {
        if (snapshot.hasData) {
          return CustomPaint(
            painter: _SpriteSheetPainter(
              image: snapshot.data!,
              spriteWidth: spriteWidth,
              spriteHeight: spriteHeight,
              rowIndex: rowIndex,
              columnIndex: columnIndex,
            ),
            size: Size(spriteWidth.toDouble(), spriteHeight.toDouble()),
          );
        } else {
          return const CircularProgressIndicator();
        }
      },
    );
  }

  Future<ui.Image> _loadImage() async {
    final data = await rootBundle.load(imagePath);
    final list = data.buffer.asUint8List();
    final codec = await ui.instantiateImageCodec(list);
    final frame = await codec.getNextFrame();
    return frame.image;
  }
}

class _SpriteSheetPainter extends CustomPainter {
  final ui.Image image;
  final int spriteWidth;
  final int spriteHeight;
  final int rowIndex;
  final int columnIndex;

  _SpriteSheetPainter({
    required this.image,
    required this.spriteWidth,
    required this.spriteHeight,
    required this.rowIndex,
    required this.columnIndex,
  });

  @override
  void paint(Canvas canvas, Size size) {
    final srcRect = Rect.fromLTWH(
      columnIndex * spriteWidth.toDouble(),
      rowIndex * spriteHeight.toDouble(),
      spriteWidth.toDouble(),
      spriteHeight.toDouble(),
    );
    final dstRect = Rect.fromLTWH(0, 0, size.width, size.height);
    canvas.drawImageRect(image, srcRect, dstRect, Paint());
  }

  @override
  bool shouldRepaint(covariant CustomPainter oldDelegate) {
    return false;
  }
}

相关问题