コンサルティング事業について詳しく知りたい方はこちら
前回までのおはなし
Flutter × UI #01 ~ agexコーポレートサイトをトレースしてみた (ヘッダー編) ~
Flutter × UI #02 ~ agexコーポレートサイトをトレースしてみた (スライダー編 part1) ~
今回のおはなし
今回は、弊社HPの「スライダー」をFlutterで再現した際のおはなし part2です。
引きづづき、実装を進めていきます。
[ここまでの成果]
・アイテムの形は平行四辺形
・アイテムは水平方向に、一定間隔で配列されている
・アイテムは一定時間間隔で自動的にスライドされる
・アイテムのスライドは左方向
・アイテムが最左端へスライドする際、アイテムのサイズが大きくなる
・最左端のアイテムのみ、最右端へスライドする
・最右端へのスライド時、アイテムはフェードアウトアニメーションがついている
・最右端へのスライド時、アイテムは他要素の後ろ側を通過する
・マウスがアイテム内へ移動すると、アイテム内画像がズームされる
・マウスがアイテム外へ移動すると、アイテム内画像は元サイズへズームアウトされる
・スライダー下部には、最左端アイテムについてのアイテム説明が配置される
・アイテム説明は、アイテムのスライドに合わせてフェードアニメーションによって切り替わる
・スライダー下部のアイテム説明右側に、スライドボタンが配置される
・マウスがスライドボタン内に移動すると、スライドボタンは各方向に少し移動する
・マウスがスライドボタン外に移動すると、スライドボタンは元の位置に移動する
再現してみる
まだ1項目しか実装完了していませんが、のんびりやっていきます。
アイテムは水平方向に、一定間隔で配列されている
これは、「Stack」Widgetと、「Positioned」Widgetを組み合わせて再現していくことにします。
また、各アイテム間の間隔は「10」とします。
// アイテムの各パラメータ指定
double width = 200;
double height = 320;
double offset = 50;
Stack(
children: [
Positioned(
top: 0,
left: ((width – offset) + 10) * 0, // ((width – offset) + 10) * 要素の位置インデックス
child: SliderItem( // n個目のアイテム
height: height,
width: width,
offset: offset,
imagePath: “foo/bar”, // 画像のパスを指定
),
),
Positioned(
top: 0,
left: ((width – offset) + 10) * 1, // ((width – offset) + 10) * 要素の位置インデックス
child: SliderItem( // n個目のアイテム
height: height,
width: width,
offset: 50,
imagePath: “foo/bar”, // 画像のパスを指定
),
),
・
・
・
Positioned(
top: 0,
left: ((width – offset) + 10) * (アイテム数 – 1), // ((width – offset) + 10) * 要素の位置インデックス
child: SliderItem( n個目のアイテム
height: height,
width: width,
offset: offset,
imagePath: “foo/bar”, // 画像のパスを指定
),
),
],
)
これで、シンプルにアイテムを配列するところまでは再現できました。
アイテムは一定時間間隔で自動的にスライドされる
アイテムのスライドは左方向
これは、「Positioned」Widgetの「left」プロパティを、一定時間間隔で変化させることで実現します。
スライド方向は左方向なので、初期位置が最右端のアイテムを基準に、実装方法を考えていきます。
「Positioned」Widgetの「left」プロパティには「((width – offset) + 10) * 要素の位置インデックス」で算出される値を格納しています。
この中の「要素の位置インデックス」を時間経過とともに減少させることで、アイテムを左方向へとスライドさせることができます。
時間経過とともに減少する値(tIndex)は、「Timer」を利用して作成します。
pIndexは、このTimerを使って作成した値を使うことで算出することができます。
int itemCount = /* 全アイテム数 */
int tIndex = itemCount;
int iIndex = /* 各アイテムの初期位置インデックス */
int pIndex = ((tIndex % itemCount) + iIndex) % itemCount; /* 要素の位置インデックス */
Timer timer = Timer.periodic(
Duration(seconds: 3),
_timerHandler,
);
void _timerHandler(Timer timer) {
tIndex = tIndex == 1 ? itemCount : tIndex – 1;
setState(() {});
}
想定していたよりpIndexの計算が複雑になってしまいました。。
表にまとめると、各indexの値は下記の通りとなり、「要素の位置インデックスを時間経過とともに減少させる」ことができました!
○ 時間経過ごとの各index値
これらを利用して、スライドするアイテムを作成していきます。
アイテムには、現状「Positioned」Widgetを利用していますが、アイテムの位置をアニメーションで変化させたいため「AnimatedPositioned」Widgetに変更します。
AnimatedPositioned(
key: ValueKey(iIndex),
curve: Curves.easeOut,
duration: Duration(seconds: 1),
top: 0,
left: ((width – offset) + 10) * pIndex,
child: SliderItem(
height: height,
width: width,
offset: offset,
imagePath: “foo/bar”,
),
),
これらを組み合わせることで、下記のように時間経過とともに自動でスライドするスライダーを作ることができます。
[ここまでの成果]
・アイテムの形は平行四辺形
・アイテムは水平方向に、一定間隔で配列されている
・アイテムは一定時間間隔で自動的にスライドされる
・アイテムのスライドは左方向
・アイテムが最左端へスライドする際、アイテムのサイズが大きくなる
・最左端のアイテムのみ、最右端へスライドする
・最右端へのスライド時、アイテムはフェードアウトアニメーションがついている
・最右端へのスライド時、アイテムは他要素の後ろ側を通過する
・マウスがアイテム内へ移動すると、アイテム内画像がズームされる
・マウスがアイテム外へ移動すると、アイテム内画像は元サイズへズームアウトされる
・スライダー下部には、最左端アイテムについてのアイテム説明が配置される
・アイテム説明は、アイテムのスライドに合わせてフェードアニメーションによって切り替わる
・スライダー下部のアイテム説明右側に、スライドボタンが配置される
・マウスがスライドボタン内に移動すると、スライドボタンは各方向に少し移動する
・マウスがスライドボタン外に移動すると、スライドボタンは元の位置に移動する
今回はここまでにします。
基本的なスライドアニメーションは作成することができました。
各index値の時間変化ごとの値算出に関しては、さらっと紹介しましたが結構苦戦しました。。
次回も引き続き、スライダーを作成していきます。
コンサルティング事業について詳しく知りたい方はこちら
RECOMMEND
おすすめ記事