首页 > 解决方案 > 如何为一张大图像设置动画以仅在屏幕内显示其自身的一部分?

问题描述

我有一张大图。

width = 500 px;
height = 2000 px;

我想在小部件的视口内显示该图像。在这种情况下,小部件将成为背景,它将占据屏幕的整个宽度和高度。

我在该图像上有几个断点需要与屏幕底部对齐。[1000 像素,1500 像素,2000 像素]

需要显示的是从底线到将屏幕填充到顶部的所有内容,而宽度正在被拉伸以适应屏幕。

我还想为从一种背景到另一种背景的变化设置动画。

我将如何处理这个解决方案?

我尝试使用对齐,Image.asset但我无法将对齐精确地映射到所需的断点。

    return TweenAnimationBuilder(
      curve: Curves.easeInOut,
      duration: Duration(milliseconds: 300),
      tween: Tween<double>(
          begin: alignmentForScreen(previousScreen),
          end: alignmentForScreen(currentScreen)),
      builder: (context, value, _) => Image.asset(
        "assets/imgs/bg/home_bg.jpeg",
        width: size.width,
        height: size.height,
        fit: BoxFit.fitWidth,
        alignment: Alignment(0,value),
      ),
    );

这是我要使用的图像:

它是553*2048,断点在高度处绘制为一条线

 1365
 1712
 2032

有什么建议么?

标签: flutterdart

解决方案


这很容易通过ListView嵌套在 aSizedBox

SizedBox(
  height: MediaQuery.of(context).size.height,  //Constraints of viewport to fit screen
  width: MediaQuery.of(context).size.width,  //Constraints of viewport to fit screen
  child: ListView(  //Scrollable widget
    shrinkWrap: true, //Reduce ListView's height to the childrens's
    controller: listViewController,  //Allows to programatically animate between offsets of the ListView (1365, 1712, 2032)
    physics: NeverScrollableScrollPhysics(),  //The user can't swipe the picture up or down
    scrollDirection: Axis.vertical,
    children: [
      Image.asset("assets/svg/ZFh5j.jpg", fit: BoxFit.fitHeight) //BigImage
    ],
  ),
),

ListView要在添加 a中的偏移量之间进行动画处理ScrollController

class Screen extends StatefulWidget {
  Screen({Key key}) : super(key: key);

  @override
  _ScreenState createState() => _ScreenState();
}

class _ScreenState extends State<Screen> {
  ScrollController listViewController = ScrollController(initialScrollOffset: 0);

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Stack(
        children: [
          SizedBox(
            height: MediaQuery.of(context).size.height,  //Constraints of viewport to fit screen
            width: MediaQuery.of(context).size.width,  //Constraints of viewport to fit screen
            child: ListView(  //Scrollable widget
              shrinkWrap: true, //Reduce ListView's height to the childrens's
              controller: listViewController,  //Allows to programatically animate between offsets of the ListView (1365, 1712, 2032)
              physics: NeverScrollableScrollPhysics(),  //The user can't swipe the picture up or down
              scrollDirection: Axis.vertical,
              children: [
                Image.asset("assets/svg/ZFh5j.jpg") //BigImage
              ],
            ),
          ),
          //contents on top of the background here
        ],
      ),
    );
  }
}

ListView然后你可以像这样为 ' 位置设置动画:

(你可以把这个函数放在一个GestureDetector.ListView在动画它之前必须已经构建)

listViewController.animateTo(/*offset*/, duration: Duration(milliseconds: 500), curve: Curves.easeInOutQuad);

这将从顶部滚动ListView到“偏移”像素,因此动画到偏移2032不会将图像的下线与视口的底部约束对齐。为方便起见,SizedBox请在ListView图像前添加一个

SizedBox(
  height: MediaQuery.of(context).size.height,  //Constraints of viewport to fit screen
  width: MediaQuery.of(context).size.width,  //Constraints of viewport to fit screen
  child: ListView(  //Scrollable widget
    shrinkWrap: true, //Reduce ListView's height to the childrens's
    controller: listViewController,  //Allows to programatically animate between offsets of the ListView (1365, 1712, 2032)
    physics: NeverScrollableScrollPhysics(),  //The user can't swipe the picture up or down
    scrollDirection: Axis.vertical,
    children: [
      SizedBox(height: MediaQuery.of(context).size.height), //Must be height of viewport in order to work
      SizedBox(
        height: 2048,
        width: 553,
        child: Image.asset("assets/svg/ZFh5j.jpg", fit: BoxFit.fitHeight,) //BigImage
      )
    ],
  ),
),

现在调用listViewController.animateTo(2032, duration: Duration(milliseconds: 500), curve: Curves.easeInOutQuad)应该将下一行与视口的底部对齐


推荐阅读