あのルーレットを作ってみた

* ネタというのを前提に見てください
* なんのことをは言いません。とりあえずアレです
* 鉄は熱いうちに打て。Flutter/dartです

ルーレットアプリ作りました！必ず「+90kg」で止まります。
とりあえずソースコード


```dart

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: RouletteScreen(),
    );
  }
}

class RouletteScreen extends HookWidget {
  @override
  Widget build(BuildContext context) {

    // 回転時間
    int time = 10;

    final List<String> items = [
      '-57kg', // 女子
      '-73kg', // 男子
      '-70kg',
      '-90kg',
      '+70kg',
      '+90kg',
    ];

    ScrollController scrollController = useScrollController(
      keepScrollOffset: false
    );
    AnimationController animationController = useAnimationController(
      duration: Duration(seconds: 5),
    );

    useEffect(() {
      animationController.addStatusListener((status) {
        if (status == AnimationStatus.forward) {
          int targetIndex = items.indexOf('+90kg');
          WidgetsBinding.instance.addPostFrameCallback((_) {
            scrollController.animateTo(
              targetIndex * 50.0,
              duration: Duration(milliseconds: 500),
              curve: Curves.easeOut,
            );
          });
        }

        if (status == AnimationStatus.completed) {
          int targetIndex = items.indexOf('+90kg');
          WidgetsBinding.instance.addPostFrameCallback((_) {
            scrollController.animateTo(
              targetIndex * 50.0,
              duration: Duration(milliseconds: 500),
              curve: Curves.easeOut,
            );
          });
        }
      });
      return null;
    }, [animationController]);

    void startRoulette() {

      // 回転時間：3~10秒
      time =  math.Random().nextInt(10 - 3);
      time + 3;
      animationController.duration = Duration(seconds: time);

      animationController.reset();
      // double maxScrollExtent = scrollController.position.maxScrollExtent;
      scrollController.animateTo(
        100,
        duration: animationController.duration!,
        curve: Curves.linear,
      );
      animationController.forward();
    }

    return Scaffold(
      appBar: AppBar(
        title: Text('ドラムロール型ルーレット'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            SizedBox(
              height: 200,
              width: 100,
              child: ListWheelScrollView.useDelegate(
                controller: scrollController,
                itemExtent: 50,
                physics: const FixedExtentScrollPhysics(),
                childDelegate: ListWheelChildLoopingListDelegate(
                  children: items.map((item) => Center(child: Text(item))).toList(),
                ),
              ),
            ),
            SizedBox(height: 20),
            ElevatedButton(
              onPressed: startRoulette,
              child: Text('Start'),
            ),
          ],
        ),
      ),
    );
  }
}

```

# 実装結果

とりあえず3回実行した動画キャプチャ

|![Screen_recording_20240807_110800.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238700/c5ef4f04-8e9b-4e50-6f67-3caca7c5a2be.gif)|![Screen_recording_20240807_110835.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238700/22fac099-d62b-3e39-416c-fea80fca0517.gif)|![Screen_recording_20240807_110822.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238700/b476a4ce-30c5-c81c-7769-a9f62697a7a2.gif)|
|---|---|---|
|1回目|2回目|3回目|

# やること
* 止まった時に拡大するアニメーション
* 男子：青、女子：赤のに文字色を変更
* 回転スピード上げる

iOS/Androidアプリ申請する。通れば。。多分無理。。