6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

Flutterで背景画像を回転させる

Last updated at Posted at 2020-05-09

前々回前回に引き続き、今度は背景に関わる部分です。

実装したもの

背景全体を回転させます。
画面内に収まっている画像を回転させるのはかんたんでしたが、"全体"ということで画面の高さと同じ幅を持つ画像を描画する必要があり、少し面倒でした。

test.gif

回転させている画像は、 https://material.io/resources/icons/?style=baseline からダウンロードしたSVG画像です。

コード

全文はこちら

コード説明

import 'package:flutter/material.dart';
import 'package:flutter_svg/flutter_svg.dart';

class RotateBackgroundScreen extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text('Rotate background'),
      ),
      body: Stack(
        children: <Widget>[
          _RotateBackground(),
          _Screen(),
        ],
      ),
    );
  }
}

画面全体としては、このようになります。
Scaffoldの子要素として、"背景"Widgetと"その他画面要素"Widgetを重ねるイメージです。

class _RotateBackground extends StatefulWidget {
  @override
  _RotateBackgroundState createState() => _RotateBackgroundState();
}

AnimationController無しにrotateさせる方法が見当たらなかったので、StatefulWidgetとしています。

class _RotateBackgroundState extends State<_RotateBackground>
    with SingleTickerProviderStateMixin {
  AnimationController _animationController;
  Animation<double> _turns;

  @override
  void initState() {
    super.initState();
    _animationController = AnimationController(
      vsync: this,
      duration: const Duration(seconds: 5),
    );
    _turns = _animationController
        .drive(
          CurveTween(curve: Curves.linear),
        )
        .drive(
          Tween<double>(begin: 0, end: 1),
        );

    _animationController.repeat();
  }

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

5秒間で1回転するアニメーションを、リピートさせています。

  @override
  Widget build(BuildContext context) {
    final screenHeight = MediaQuery.of(context).size.height;
    return ClipRect(
      child: OverflowBox(
        minWidth: 0.0,
        minHeight: 0.0,
        maxWidth: screenHeight,
        maxHeight: screenHeight,
        child: RotationTransition(
          turns: _turns,
          alignment: Alignment.center,
          child: SvgPicture.asset(
            'assets/bg.svg',
            width: screenHeight,
            height: screenHeight,
          ),
        ),
      ),
    );
  }
}

RotationTransition に、先に出ていた _trans を渡すことで、SvgPictureが回転します。
SvgPictureに、表示領域の高さで縦横の大きさを与えているのですが、外側の OverflowBox を指定しない場合は、以下のように画面幅に制限されてしまいます。

test.gif

さらに、その外側を ClipRect で囲むことで、以下のように画面遷移のタイミングで変に見えてしまうことを防いでいます。
(画面の大きさを飛び越えて、SVG画像が表示されてしまっている。)

test.gif

終わり

OverflowBoxClipRect を利用することで、画面外に画像を描画しつつ、アニメーションで見せることができました。
これを転用して、キャラクターが横から出たり引っ込んだりするUIも作れそうですね。

「どれだけのWidgetを知っているか」で実装できる幅が変わってきそうなので、 https://www.youtube.com/playlist?list=PLjxrf2q8roU23XGwz3Km7sQZFTdB996iG を流し見ておくのは大事かもしれません。

6
4
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?