如何围绕指定的锚点旋转 2D 容器小部件?

Posted

技术标签:

【中文标题】如何围绕指定的锚点旋转 2D 容器小部件?【英文标题】:How can I rotate a Container widget in 2D around a specified anchor point? 【发布时间】:2017-05-26 23:11:14 【问题描述】:

我想执行一个非常简单的 Container 小部件(包含一些其他小部件)的 2D 旋转。这个小部件将围绕中心的一个固定点旋转,没有变形。

我尝试将transform 属性与Matrix4.rotationZ 一起使用,这有点工作 - 但锚点位于左上角角,而不是中心 .有没有一种简单的方法来指定该锚点?

此外,有没有更简单的方法来 2D 旋转这个不需要 Matrix4 的小部件?

var container = new Container (
  child: new Stack (
    children: [
      new Image.asset ( // background photo
        "assets/texture.jpg",
        fit: ImageFit.cover,
      ),
      new Center (
        child: new Container (
          child: new Text (
            "Lorem ipsum",
            style: new TextStyle(
              color: Colors.white,
              fontSize: 42.0,
              fontWeight: FontWeight.w900
            )
          ),
          decoration: new BoxDecoration (
            backgroundColor: Colors.black,
          ),
          padding: new EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 16.0),
          transform: new Matrix4.rotationZ(0.174533), // rotate -10 deg
        ),
      ),
    ],
  ),
  width: 400.0,
  height: 200.0,
);

【问题讨论】:

【参考方案1】:

根据 Ian 的建议,我尝试了以下方法。它似乎有效,至少在我有限的测试中。

容器嵌套在Transform widget 中。使用alignment 可以相对调整变换原点,即在中心、左上角等。

var container = new Container (
  child: new Stack (
    children: [
      new Image.asset ( // background photo
        "assets/texture.jpg",
        fit: ImageFit.cover,
      ),
      new Center (
        child: new Transform (
          child: new Container (
            child: new Text (
              "Lorem ipsum",
              style: new TextStyle(
                color: Colors.white,
                fontSize: 42.0,
                fontWeight: FontWeight.w900,
              )
            ),
            decoration: new BoxDecoration (
              backgroundColor: Colors.black,
            ),
            padding: new EdgeInsets.fromLTRB(16.0, 16.0, 16.0, 16.0),              
          ),
          alignment: FractionalOffset.center, // set transform origin
          transform: new Matrix4.rotationZ(0.174533), // rotate -10 deg
        ),
      ),
    ],
  ),
  width: 400.0,
  height: 200.0,
);

【讨论】:

pub.dev/packages/matrix4_transform 这是一个非常有用的转换包。【参考方案2】:

您可以使用 RotatedBox Widget 来旋转任何小部件:

RotatedBox(
    quarterTurns: 3,
    child: Container(
        color:Colors.red
    ),
),

【讨论】:

可能值得注意的是,您只能旋转四分之一圈,不能有分数。 这个可以动画吗?【参考方案3】:

在颤振 2.2 中

使用变换:

Transform(
    transform: Matrix4.rotationZ(...),
    alignment: FractionalOffset.center,
    child: Container(...)

或者在Container中设置transformAlignment值:

Container(
    ...
    transform: Matrix4.rotationZ(...),
    transformAlignment: Alignment.center,
)

【讨论】:

【参考方案4】:

在旋转之前和之后应用平移(到支点和从支点)。

您可以自己创建一个小部件来执行此操作,从而同时解决您的其他问题(隐藏 Matrix4)。

【讨论】:

【参考方案5】:

对于像我一样想要制作应用程序的人,只需使用Transform 和Gesturedetector。请记住不要同时使用 Draggable 和 Gesturedetector,因为您只能拖放而不能缩放小部件:))。

参考: A Deep Dive Into Transform Widgets in Flutter

barbswatanabe

:

             Transform.rotate(
                  alignment: FractionalOffset.center,
                  angle: state.listStickerModel[index].angle,
                  child: Transform(
                    alignment: FractionalOffset.center,
                    transform: new Matrix4.diagonal3(vector.Vector3(
                        state.listStickerModel[index].zoom,
                        state.listStickerModel[index].zoom,
                        state.listStickerModel[index].zoom)),
                    child: GestureDetector(
                      onScaleStart: (detail) 
                        _editPhotoBloc.add(UpdateSticker(
                          index: index,
                          offset: detail.focalPoint,
                          previousZoom: state.listStickerModel[index].zoom,
                        ));
                      ,
                      onScaleUpdate: (detail) 
                        _editPhotoBloc.add(UpdateSticker(
                            index: index,
                            offset: Offset(detail.localFocalPoint.dx,
                                detail.focalPoint.dy),
                            angle: detail.rotation,
                            zoom:
                                state.listStickerModel[index].previousZoom *
                                    detail.scale));
                      ,
                      child: Container(
                        alignment: Alignment.center,
                        child: SvgPicture.asset(
                            state.listStickerModel[index].src),
                      ),
                    ),
                  ),
                ),

【讨论】:

以上是关于如何围绕指定的锚点旋转 2D 容器小部件?的主要内容,如果未能解决你的问题,请参考以下文章

iOS核心动画:旋转的锚点不正确

如何在颤动中更改容器小部件中的背景图像

如何多次围绕锚点旋转视图

如何在 FLUID gui 编辑器中旋转小部件

如何更改 GTK 容器小部件的大小?

Flutter:如何防止我的主要小部件旋转并仍然跟踪它的方向?