溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶(hù)服務(wù)條款》

Android?Flutter如何實(shí)現(xiàn)3D動(dòng)畫(huà)效果

發(fā)布時(shí)間:2022-03-24 09:15:21 來(lái)源:億速云 閱讀:206 作者:iii 欄目:開(kāi)發(fā)技術(shù)

這篇文章主要講解了“Android Flutter如何實(shí)現(xiàn)3D動(dòng)畫(huà)效果”,文中的講解內(nèi)容簡(jiǎn)單清晰,易于學(xué)習(xí)與理解,下面請(qǐng)大家跟著小編的思路慢慢深入,一起來(lái)研究和學(xué)習(xí)“Android Flutter如何實(shí)現(xiàn)3D動(dòng)畫(huà)效果”吧!

AnimatedWidget 簡(jiǎn)介

AnimatedWidget是一個(gè)抽象的 StatefulWidget, 構(gòu)造方法如下所示。

const AnimatedWidget({
    Key? key,
    required this.listenable,
  }) : assert(listenable != null),
       super(key: key);

主要在于接收一個(gè) listenable 參數(shù),通常會(huì)是 Animation 對(duì)象。在 AnimatedWidget 內(nèi)部的_AnimatedState 類(lèi)中,會(huì)添加該對(duì)象變化監(jiān)聽(tīng)回調(diào),進(jìn)而刷新界面。

class _AnimatedState extends State<AnimatedWidget> {
  @override
  void initState() {
    super.initState();
    widget.listenable.addListener(_handleChange);
  }

  @override
  void didUpdateWidget(AnimatedWidget oldWidget) {
    super.didUpdateWidget(oldWidget);
    if (widget.listenable != oldWidget.listenable) {
      oldWidget.listenable.removeListener(_handleChange);
      widget.listenable.addListener(_handleChange);
    }
  }

  @override
  void dispose() {
    widget.listenable.removeListener(_handleChange);
    super.dispose();
  }

  void _handleChange() {
    setState(() {
      // The listenable's state is our build state, and it changed already.
    });
  }
  
  // ...
}

可以看到,只需要將 Animation 對(duì)象傳給 AnimatedWidget 對(duì)象后,就不需要我們之前那樣自己寫(xiě) addListener 之類(lèi)的處理了。而整個(gè)動(dòng)畫(huà)可以交給外部其他對(duì)象來(lái)控制,從而實(shí)現(xiàn)動(dòng)畫(huà)組件的復(fù)用。

3D 旋轉(zhuǎn)動(dòng)畫(huà)的實(shí)現(xiàn)

3D 旋轉(zhuǎn)的實(shí)現(xiàn)比較簡(jiǎn)單,在 Container 組件有兩個(gè)參數(shù)控制轉(zhuǎn)換(transform),分別是:

  • transformMatrix4對(duì)象,可以實(shí)現(xiàn)圍繞 X、Y、Z軸的旋轉(zhuǎn)、平移,以及變形等效果。關(guān)于 Matrix4涉及到很多矩陣運(yùn)算和線(xiàn)性代數(shù)的知識(shí),可以參考 Matrix4的源碼自行溫習(xí)一下大學(xué)的數(shù)學(xué)知識(shí)。

  • transformAlignment:轉(zhuǎn)換的對(duì)齊方式,可以理解為起點(diǎn)位置,可以使用 Alignment 對(duì)象來(lái)設(shè)置。

有了這個(gè)基礎(chǔ),我們就可以定義3D 旋轉(zhuǎn)動(dòng)效了,我們定義一個(gè)通用的組件,ThreeDAnimatedWidget

class ThreeDAnimatedWidget extends AnimatedWidget {
  final Widget child;
  const ThreeDAnimatedWidget(
      {Key? key, required Animation<double> animation, required this.child})
      : super(key: key, listenable: animation);

  @override
  Widget build(BuildContext context) {
    final animation = listenable as Animation<double>;

    return Center(
      child: Container(
        transform: Matrix4.identity()
          ..rotateY(2 * pi * animation.value)
          ..setEntry(1, 0, 0.01),
        transformAlignment: Alignment.center,
        child: child,
      ),
    );
  }
}

這里我們?cè)O(shè)置的是圍繞中心點(diǎn)繞 Y 軸旋轉(zhuǎn),并使用 setEntry 設(shè)置了一定的傾斜角 (這會(huì)更有立體感)。實(shí)際我們也可以設(shè)置圍繞 X 軸或 Z 軸旋轉(zhuǎn)。接下來(lái)就是這個(gè)動(dòng)畫(huà)組件的應(yīng)用了,我們構(gòu)建一個(gè)帶有陰影的文字(看起來(lái)像立體字)作為這個(gè)動(dòng)畫(huà)的子組件,其他的控制和上一篇的是類(lèi)似的,完整代碼如下:

class AnimatedWidgetDemo extends StatefulWidget {
  const AnimatedWidgetDemo({Key? key}) : super(key: key);

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

class _AnimatedWidgetDemoState extends State<AnimatedWidgetDemo>
    with SingleTickerProviderStateMixin {
  late Animation<double> animation;
  late AnimationController controller;

  @override
  void initState() {
    super.initState();
    controller =
        AnimationController(duration: const Duration(seconds: 3), vsync: this);
    animation = Tween<double>(begin: 0.0, end: 1.0).animate(controller);
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('AnimatedWidget 動(dòng)畫(huà)'),
      ),
      body: ThreeDAnimatedWidget(
        animation: animation,
        child: Text(
          '島上碼農(nóng)',
          style: TextStyle(
            fontSize: 42.0,
            color: Colors.blue,
            fontWeight: FontWeight.bold,
            shadows: [
              Shadow(
                  blurRadius: 2,
                  offset: Offset(2.0, 1.0),
                  color: Colors.blue[900]!),
            ],
          ),
        ),
      ),
      floatingActionButton: FloatingActionButton(
        child: Icon(Icons.play_arrow, color: Colors.white),
        onPressed: () {
          if (controller.status == AnimationStatus.completed) {
            controller.reverse();
          } else {
            controller.forward();
          }
        },
      ),
    );
  }

  @override
  void dispose() {
    controller.dispose();
    super.dispose();
  }
}

可以看到,這個(gè) ThreeDAnimatedWidget 可以做到復(fù)用了,在需要這樣動(dòng)效的場(chǎng)景里,按照上面的方式給它傳入 Animation 對(duì)象和子組件就可以了。例如我們將文字修改為一張圖片。

//...
body: ThreeDAnimatedWidget(
  animation: animation,
  child: Image.asset(
    'images/avatar.jpg',
    width: 100,
    height: 100,
  ),
),
//...

Android?Flutter如何實(shí)現(xiàn)3D動(dòng)畫(huà)效果

感謝各位的閱讀,以上就是“Android Flutter如何實(shí)現(xiàn)3D動(dòng)畫(huà)效果”的內(nèi)容了,經(jīng)過(guò)本文的學(xué)習(xí)后,相信大家對(duì)Android Flutter如何實(shí)現(xiàn)3D動(dòng)畫(huà)效果這一問(wèn)題有了更深刻的體會(huì),具體使用情況還需要大家實(shí)踐驗(yàn)證。這里是億速云,小編將為大家推送更多相關(guān)知識(shí)點(diǎn)的文章,歡迎關(guān)注!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI