スタイルシート ルーレット の説明
戻る


JavaScript を使わず,スタイルシートだけでルーレットを作ってみます.
全くのお遊びです.これが何か実用の役に立つようなことは多分無いでしょう.スタイルシートは本来,動作を記述するものではありませんので,かなり力ずくで作っています.
画面
(これはキャプチャ画像です.これで遊ぶことはできません.)
使い方と仕組みについて説明します.


使い方

「選択肢数」で選択肢の数を選びます.

盤面の選択肢をクリックすると,その選択肢のテキストを入力できる状態になるので,テキストの文字列を入力します.
選択肢入力 1
選択肢入力 2
選択肢以外の場所をクリックすると入力を終了します.

「スタート」をクリックするとルーレットが回転を始めます.
スタートすると「スタート」ボタンの表示が「ストップ」に変わります.「ストップ」をクリックするとルーレットが次第に減速し,停止します.



回転のさせ方

transformrotate 関数でルーレットの盤面を回転させます.
このような指定で,カスタム プロパティの --theta1--theta2 の値を加算した角度の回転をさせます.
transform:rotate(calc((var(--theta1) + var(--theta2)) * 1deg));
--theta1 は「スタート」をクリックしてから「ストップ」をクリックするまでの間の等速回転時の角度で,--theta2 は「ストップ」をクリックしてから停止するまでの減速時の角度です.
「スタート」から「ストップ」までの間は,次のようなアニメーションで 360 度の回転を継続して行うようにします.(実際のプログラム(?)では,二度目以降に回転させたときに再度初期位置から回転を始めるよう,これとは少し異なった処理になっています.)
@keyframes rotate {
  from {
    --theta1:0;
  }
  to {
    --theta1:360;
  }
}

animation:rotate 3s linear infinite;
「ストップ」をクリックしたら,等速回転のアニメーションを停止します.
animation:rotate 3s linear infinite paused;
そして,次のようなアニメーションで,カスタム プロパティ --decel-t の値の時間(秒)で停止させます.
--theta2:calc(var(--decel-t) * 60);
transition:--theta2 calc(var(--decel-t) * 1s) cubic-bezier(0.3333333, 0.6666667, 0.6666667, 1);
初めは速く減速して,だんだん減速の仕方がゆっくりになるように,タイミング関数にベジェ曲線を使っています.
cubic-bezier(0.3333333, 0.6666667, 0.6666667, 1)
このベジェ曲線は放物線になります.つまり,回転の角度が放物線のグラフに沿って増加します.
放物線のグラフ
等速回転時は 3 秒で 1 周,つまり 120 度/秒 の角速度で回転しています.私の理解が正しければ,放物線に沿って減速させる場合,減速時間が T 秒なら停止するまでに T × 60 度 回転するように設定すれば,減速開始時の角速度が等速時と同じ 120 度/秒 になるはずです.つまり,等速から減速に滑らかに移行します.


減速時間のランダム化

「ストップ」をクリックしてからルーレットが停止するまでの時間がばらつくよう,以下のような処理をしています.

減速時間をアニメーションを使って決めます.
アニメーションで直接減速時間を変化させて,それを減速のアニメーションに使えれば楽なのですが,それはできません.アニメーションのプロパティをアニメーションすることはできないので,アニメーションで減速時間を決めても,それを減速のアニメーションに使うことはできません.
そのため,次のような方法で間接的に減速時間を決めます.

減速時間を 5 種類用意してそれに 0 〜 4 の数値を対応させ,アニメーションを使ってその数値を選びます.
@keyframes decel {
  from {
    --decel:0;
  }
  to {
    --decel:4;
  }
}

animation:decel 1s steps(5, jump-none) infinite;
5 個の「ストップ」ボタンを用意して,各減速時間と対応させます.それを同じ位置に重ねて配置して,一番前面にある物だけが見えている状態にします.
ストップ ボタンの重なり 1
アニメーションで設定された減速時間に合わせて「ストップ」ボタンの Z オーダーを変え,該当の「ストップ」ボタンが前面になるようにします.
その状態でボタンをクリックすると,前面のボタンがクリックされ,そのボタンに対応するセレクタが有効になります.
ストップ ボタンの重なり 2
各ボタンのセレクタで,該当の減速時間を設定して減速の処理を開始します.

減速時間を選ぶアニメーションは「ストップ」から次の「スタート」までの間に行います.「ストップ」をクリックしたらアニメーションを開始し,「スタート」をクリックしたらアニメーションを停止します.そのとき選ばれていた「ストップ」ボタンが,次に「ストップ」をクリックしたときにクリックされるボタンです.


カスタム プロパティの定義

このプログラムでは,いくつかのカスタム プロパティを @ルールの @property で定義しています.
@property の定義は,たとえばこのように書きます.
@property --a {
  syntax:'<integer>';
  inherits:true;
  initial-value:0;
}
このプログラムでは,カスタム プロパティにアニメーション(transition も含む)を使っているところがあります.カスタム プロパティに計算値によるアニメーションや transition を使うためには,プロパティのデータ型を定義する必要があります.
@propertysyntax<number><integer> を指定することで,そのプロパティを計算値によるアニメーション可能にしています.

また,計算結果の小数を整数に丸めるためにも @property を使っています.整数のプロパティを定義して,計算結果をそのプロパティに設定することで,整数への丸めを行っています.


このおもちゃは Firefox 128 以上および Opera 80 以上用に作っていますが,Google Chrome 107 で動くことが確認できています.Google Chrome の他のバージョンでの動作は未確認です.


戻る