🗺️

【Flutter】大きな画像のどこか一部分を表示する

2023/06/16に公開

やりたいこと

大きなSVG画像を用意する
そのうちのどこか一部を表示する。



はじめにお願い

自分が知っている知識だけで強引にやったと思っています。もっといい方法があれば教えてください。参考にする場合は他にいいやり方がないか十分注意してください。

注意

画像は正方形とする。

実装

PointedMap という自作のウィジェットを作成した。

PointedMapを使うところ

次のようにして使う。

LayoutBuilder(
    builder: (context, constraints) {
    return PointedMap(
        name: 'assets/images/PrefAll.svg',
        w: constraints.maxWidth,
        h: constraints.maxHeight,
        enlarge: 5,
        centerX: 0.3,
        centerY: 0.7);
    },
),

name 画像の名前
w この場所の大きさ
h この場所の大きさ
enlarge 与えられた領域に比べてどれくらい画像を大きくするか
centerX 中心位置x
centerY 中心位置y

PointedMap

class PointedMap extends StatelessWidget {
  final String name;
  final double w;
  final double h;
  final double enlarge;
  final double centerX;
  final double centerY;

  const PointedMap(
      {required this.name,
      required this.w,
      required this.h,
      required this.enlarge,
      required this.centerX,
      required this.centerY,
      Key? key})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    double size = (w < h ? w : h) * enlarge;
    ScrollController scX =
        ScrollController(initialScrollOffset: size * centerX);
    ScrollController scY =
        ScrollController(initialScrollOffset: size * centerY);

    return Container(
      clipBehavior: Clip.antiAlias,
      decoration: const BoxDecoration(),
      child: Center(
        child: Container(
          clipBehavior: Clip.none,
          height: 1,
          width: 1,
          child: SingleChildScrollView(
            controller: scY,
            clipBehavior: Clip.none,
            child: SingleChildScrollView(
              controller: scX,
              clipBehavior: Clip.none,
              scrollDirection: Axis.horizontal,
              child: SizedBox(
                height: size,
                width: size,
                child: SvgPicture.asset(
                  name,
                  fit: BoxFit.cover,
                ),
              ),
            ),
          ),
        ),
      ),
    );
  }
}

改良型PointedMap

class PointedMap3 extends StatelessWidget {
  final String name;
  final double w;
  final double h;
  final double enlarge;
  final double centerX;
  final double centerY;

  const PointedMap3(
      {required this.name,
      required this.w,
      required this.h,
      required this.enlarge,
      required this.centerX,
      required this.centerY,
      Key? key})
      : super(key: key);

  @override
  Widget build(BuildContext context) {
    double size = (w < h ? w : h);

    return Center(
      child: SizedBox(
        height: size,
        width: size,
        child: FractionallySizedBox(
          heightFactor: enlarge * 2,
          widthFactor: enlarge * 2,
          child: Align(
            alignment: Alignment(1 - centerX * 2, 1 - centerY * 2),
            child: SizedBox(
              height: size * enlarge,
              width: size * enlarge,
              child: Image.asset(
                name,
                fit: BoxFit.fill,
              ),
            ),
          ),
        ),
      ),
    );
  }
}

Discussion