無意味にスクロールするあなたへ贈る、スクロールするだけのゲーム
はじめに
つい考え事をする時、無意味に画面をスクロールしていませんか?
XやSlackを見るでもなく、ただボーッとスクロール。
そんな「無意識のスクロール癖」を持つあなた(と筆者)のために、スクロールそのものをゲームにしてしまいました。
作ったもの
その名も 「スクロールタイムアタック」 🏃💨
ルールは簡単。ただ 300m スクロールするだけ。
それだけです。本当にそれだけです。

300m スクロールしたあなたには、達成時間と特別なメッセージが贈られます。

なぜこんなものを作ったのか
くだらないから
クソアプリアドベントカレンダーに相応しい、圧倒的にくだらないアプリを作りたかったからです。
「ゲーム」と名乗っていますが、戦略もスキルも不要。
ただひたすらスクロールするだけ。
誰かと競うわけでもなく、自己ベストを目指すわけでもない。
あなたの貴重な時間を、何の生産性もなく消費します。
データ非依存の技術を触りたかった
普段はバックエンド、インフラをメインに扱っている筆者。
データベース、API、Terraform... そういった「データを中心とした世界」にいます。
しかし最近、ふと思うことがあります。
生成AIの発展によって、世界のデータはより一層ビッグテックに握られるようになりました。
個人開発者がGoogleやOpenAIと同じ規模のデータを持つことは不可能です。
データによる差別化は、もはや個人には難しい時代になったのかもしれません。
だからこそ、データに依存せず、ブラウザ上だけで完結する体験に興味が湧きました。
特に魅力を感じたのが Three.js。
3D 表現、アニメーション、視覚的フィードバック... これらは完全にフロントエンドの領域で、データの量や質に左右されません。
「バックエンドエンジニアが、データのいらない世界で何か作るとどうなるのか?」
そんな実験的な気持ちで、くだらないゲームを作りながら学んでみることにしました。
実装した感想
以降、本ゲームを開発した筆者の感想をつらつら述べます。
あまり興味がないと思うので飛ばしてください。
1. ユーザーの思わぬ操作への対応
元々、勉強のために作成していた本ゲーム。
ちょっと形になったので、会社の人に触ってもらったところ、思わぬ問題が発覚。
- ⌘+↓ で一気に最下部までスクロールされる
- スクロールバーを掴んで移動させられる
- キーボードの矢印キーでスクロールされる
これらは「ゲーム」として望ましくない操作方法でした。

一瞬で終わってしまう
最初は素直に scroll イベントを使っていました。
しかし、scrollイベントはどのような方法で画面をスクロールしても計測されてしまうため、ページ送りや最下層への移動ですぐにゴールまで到達してしまいます。
その対策として「マウスホイール/トラックパッド/タッチスワイプだけ」を計測するように、wheel イベントを採用しました。
実際に使ってもらって初めて気づく仕様の穴。フロントエンド開発の難しさを痛感しました。
// 状態管理
const [scrollDistanceMeters, setScrollDistanceMeters] = createSignal(0);
let accumulatedScrollPixels = 0;
// ディスプレイの物理的なサイズを推定(96 DPI を基準とし、devicePixelRatioを考慮)
const pixelToMeter = () => {
const dpi = 96 * window.devicePixelRatio; // 標準DPI × デバイスピクセル比
const pixelsPerInch = dpi;
const pixelsPerMeter = pixelsPerInch * 39.3701; // 1メートル = 39.3701インチ
return 1 / pixelsPerMeter;
};
// イベントリスナーの登録
onMount(() => {
// wheelイベント(マウス/トラックパッドのスクロールのみ)を監視
// スクロールバーのドラッグはこのイベントでは発火しないので除外される
window.addEventListener("wheel", handleWheel, { passive: false });
// タッチスクロール対応
window.addEventListener("touchstart", handleTouchStart, { passive: true });
window.addEventListener("touchmove", handleTouchMove, { passive: true });
// キーボードによるスクロールを防止
window.addEventListener("keydown", preventKeyboardScroll);
// 他の処理は省略
});
const handleWheel = (e: WheelEvent) => {
e.preventDefault();
// 下方向へのスクロールのみ計測(deltaY > 0)
if (e.deltaY > 0) {
accumulatedScrollPixels += e.deltaY;
}
// ピクセルをメートルに変換
const meters = accumulatedScrollPixels * pixelToMeter();
setScrollDistanceMeters(meters);
};
バックエンドなら入力値は API のリクエストボディとして決まった形式で来ますが、フロントエンドは ユーザーがブラウザで何をするか予測するのが難しい。
実際に使ってもらうことで初めて気づく仕様の検討漏れが多く、「想定外の操作」への対応が必要でした。
2. Three.js で視覚的フィードバック
当初の目的である、ブラウザ上だけで完結する技術として、Three.js で幾何学的なパターンが流れる背景を作りました。
背景は
- 黄金角スパイラル状に配置した大量のパーティクル
- 奥行き方向に並んだ複数のリング
の 2 レイヤー構成です。パーティクルは ShaderMaterial を使い、頂点シェーダ内で「時間」「スクロール量」「スクロール速度」に応じて位置を揺らしています。
スクロール入力は updateByScroll で「距離」と「速度」に変換し、tick でなめらかに補間してから、シェーダやリング、カメラの揺れに一括で反映しています。
「速くスクロールすると背景が激しく動き、止めると徐々に静まる」という挙動になっていて、スクロールそのものにだけ反応する 3D 背景になっています。
とりあえず動くものを作らせてみようと、GitHub Copilot(Claude Sonnet 4.5)に指示を出してプロトタイプを作らせてみました。
Three.jsを利用して、スクロールによって幾何学模様が動くようにしてください。
何もしていない時は動かないようにすることで自分で動かしている感を出してください
するともうすでにほぼ完成したものができてしまいました。
ここで気づくのは、「やばい、どこのコードが何の図形を表現して、どこでどう動かしているかわからん」ということ。
結果的にちょっとずつコードを削っていきながら、何をしているのかを理解していきました。
AI にただ作らせるだけでは、永遠に中身を理解することはできません。
しかし、AI のなかった時代にはできなかったアプローチがあります。
それが 「完成系を先に作らせて、自分で削りながら理解する」 という学習方法です。
従来は「基礎から積み上げて完成品に到達する」しかありませんでした。
でも今は、まず動くものを手に入れてから、分解して学ぶことができる。
これは現代ならではの学習メリットだと感じています。
もちろん、基礎的な学習も並行して進めました。
ICS MEDIA の Three.js 入門 などで基本概念を学びつつ、実際のコードを触りながら理解を深めていく。
AI が作ったコードと、基礎チュートリアルの往復。
この組み合わせが、最も効率的な学習法だったように思います。
おわりに
「無意味にスクロールするあなたへ贈る、スクロールするだけのゲーム」
くだらないものを作りながら、Three.js やフロントエンドの世界を学ぶことができました。
あなたも、考え事をしながら無意味にスクロールする時は、
ぜひこのゲームで「公式に無駄にして」ください。
あなたの貴重な時間を無駄にしてくれて、ありがとうございます。 🙏
Happy Scrolling! 🏃💨
Discussion