CSSroule.htm

戻る

<!DOCTYPE HTML>
<HTML LANG="ja">

<HEAD>
<META CHARSET="Shift_JIS">
<TITLE>スタイルシート ルーレット</TITLE>

<STYLE TYPE="text/css">
<!--

/* 等速回転 */
@keyframes rotate {
  from {
    --theta1:0;
  }
  to {
    --theta1:360;
  }
}

/* 等速回転リセット */
@keyframes reset {
  from, to {
    --rotate:none;
  }
}

/* 減速時間ランダム化 */
@keyframes decel {
  from {
    --decel:0;
  }
  to {
    --decel:4;
  }
}

/* 減速中 入力ディスエーブル */
@keyframes disable2 {
  from, to {
    --disable1-color:gray;
    --disable1-pointer:none;
    --disable2-color:gray;
    --disable2-pointer:none;
  }
}

/* 確定 */
@keyframes decided {
  from, 25%, 50%, 75%, to {
    --dec-vis:visible;
  }
  12.5%, 37.5%, 62.5%, 87.5% {
    --dec-vis:hidden;
  }
}

@property --theta1 {
  syntax:'<number>';
  inherits:true;
  initial-value:0;
}

@property --theta2 {
  syntax:'<number>';
  inherits:true;
  initial-value:0;
}

@property --decel {
  syntax:'<integer>';
  inherits:true;
  initial-value:0;
}

@property --round {
  syntax:'<integer>';
  inherits:true;
  initial-value:0;
}

body {
  background-color:#CCFFFF;
}

#title {
  color:#CC0000;
  font-size:large;
  font-weight:bold;
  text-align:center;
}

#start, .stop {
  display:none;
}

.disable1 {
  color:var(--disable1-color);
  pointer-events:var(--disable1-pointer);
  accent-color:var(--disable1-color);  /* Google Chrome で有効 */
}

#base1 {
  text-align:center;

  --disable1-color:canvastext;
  --disable1-pointer:auto;
  --disable2-color:black;
  --disable2-pointer:auto;

  /* 減速時間ランダム化 */
  /* 減速時間を直接アニメーションしてランダム化したいところだが,アニメーションした
     カスタム プロパティを他のアニメーションのパラメータに使うとうまく動かない.
     代わりに,減速時間を 5種類に限定し,5個のストップ ボタンに対応させて,ストップ
     ボタンをランダムに選ぶようにする. */
  animation:decel 1s steps(5, jump-none) infinite;
}

#base2 {
  display:inline-block;
  text-align:start;
  user-select:none;

  --dec-vis:hidden;
}

/* 選択肢数,選択肢 扇形クリップ用 */
/* 三角関数は実装されていない */
#n-2:checked ~ #reset #board {
  --n:2;
  --sector-clip:none;
}
#n-3:checked ~ #reset #board {
  --n:3;
  --sector-clip:polygon(0 120px, 122px -91.31px, 122px 331.31px);
}
#n-4:checked ~ #reset #board {
  --n:4;
  --sector-clip:polygon(0 120px, 122px -2px, 122px 242px);
}
#n-5:checked ~ #reset #board {
  --n:5;
  --sector-clip:polygon(0 120px, 122px 31.36px, 122px 208.64px);
}
#n-6:checked ~ #reset #board {
  --n:6;
  --sector-clip:polygon(0 120px, 122px 49.56px, 122px 190.44px);
}
#n-7:checked ~ #reset #board {
  --n:7;
  --sector-clip:polygon(0 120px, 122px 61.25px, 122px 178.75px);
}
#n-8:checked ~ #reset #board {
  --n:8;
  --sector-clip:polygon(0 120px, 122px 69.47px, 122px 170.53px);
}

#reset {
  --rotate:rotate 3s linear infinite;
}

#board {
  position:relative;
  margin-top:12px;
  text-align:center;

  --sector-angle:calc(360 / var(--n));

  --theta2:0;
  animation:rotate 3s linear infinite paused;  /* 等速回転停止 */
}

#rim {
  display:inline-block;
  position:relative;
  width:240px;
  height:240px;
  background-color:black;
  border-radius:120px;
}

#back {
  position:absolute;
  left:0;
  top:0;
  width:240px;
  height:240px;
  background-color:white;
  clip-path:circle(118.5px at 120px 120px);

  transform-origin:120px 120px;
  transform:rotate(calc((var(--theta1) + var(--theta2)) * 1deg));
}

/* 選択肢 */
.choice {
  position:absolute;
  left:120px;
  top:0;
  width:119px;
  height:240px;
  padding:0 0 0 0.5em;
  border-style:none;
  outline:none;
  text-align:center;
  clip-path:var(--sector-clip);
  transform-origin:0 120px;
}

#choice1 {
  background-color:#FF9999;
}
#choice2 {
  background-color:#99FF99;
  transform:rotate(calc(var(--sector-angle) * -1deg));
}
#choice3 {
  background-color:#FFFF99;
  transform:rotate(calc(var(--sector-angle) * -2deg));
  z-index:clamp(-1, var(--n) - 3, 0);
}
#choice4 {
  background-color:#9999FF;
  transform:rotate(calc(var(--sector-angle) * -3deg));
  z-index:clamp(-1, var(--n) - 4, 0);
}
#choice5 {
  background-color:#FF99FF;
  transform:rotate(calc(var(--sector-angle) * -4deg));
  z-index:clamp(-1, var(--n) - 5, 0);
}
#choice6 {
  background-color:#99FFFF;
  transform:rotate(calc(var(--sector-angle) * -5deg));
  z-index:clamp(-1, var(--n) - 6, 0);
}
#choice7 {
  background-color:#FFCC99;
  transform:rotate(calc(var(--sector-angle) * -6deg));
  z-index:clamp(-1, var(--n) - 7, 0);
}
#choice8 {
  background-color:#99CCFF;
  transform:rotate(calc(var(--sector-angle) * -7deg));
  z-index:clamp(-1, var(--n) - 8, 0);
}

/* 選択肢フォーカス */

/* 対象の選択肢を水平にする/隠れないように visibility を上書きする */
:is(#choice1, #choice2, #choice3, #choice4, #choice5, #choice6, #choice7, #choice8):focus {
  transform:rotate(calc((var(--theta1) + var(--theta2)) * -1deg));
  visibility:visible;
}

/* 対象以外の選択肢を隠す */
/* 対象の選択肢は隠さないように :where で詳細度を下げている */
:where(#back):focus-within .choice {
  visibility:hidden;
}

#back:focus-within {
  background-color:gray;
}

/* 確定表示を隠す */
#board:focus-within {
  --dec-vis:hidden;
}

#pointer {
  position:absolute;
  left:234px;
  top:114px;
  width:16px;
  height:12px;
  background-color:red;
  clip-path:polygon(0 6px, 16px 0, 16px 12px);
}

#button {
  position:relative;
  margin-top:24px;
  text-align:center;
}

#start-l {
  position:absolute;
  left:50%;
  top:0;
  transform:translateX(-50%);
  color:var(--disable2-color);
  pointer-events:var(--disable2-pointer);
  visibility:visible;
}

.stop-l {
  position:absolute;
  left:50%;
  top:0;
  transform:translateX(-50%);
  color:black;
  visibility:hidden;
}

#start-l, .stop-l {
  background-color:gainsboro;
  padding:4px 8px;
  border-radius:3px;
}

:is(#start-l, .stop-l):hover {
  background-color:lightgray;
}

#stop-1-l {
  z-index:calc(0 - min(var(--decel), 1));
}
/* abs() は実装されていない */
#stop-2-l {
  --w:calc(var(--decel) - 1);
  z-index:calc(0 - min(var(--w) * var(--w), 1));
}
#stop-3-l {
  --w:calc(var(--decel) - 2);
  z-index:calc(0 - min(var(--w) * var(--w), 1));
}
#stop-4-l {
  --w:calc(var(--decel) - 3);
  z-index:calc(0 - min(var(--w) * var(--w), 1));
}
#stop-5-l {
  --w:calc(var(--decel) - 4);
  z-index:calc(0 - min(var(--w) * var(--w), 1));
}

/* スタート */

#start:checked ~ #base1 {
  --disable1-color:gray;
  --disable1-pointer:none;

  animation-play-state:paused;  /* 減速時間ランダム化停止 */
}

#start:checked ~ #base1 #base2 #reset {
  animation:reset 1ms step-start;  /* 等速回転リセット */
}

#start:checked ~ #base1 #base2 #reset #board {
  animation:var(--rotate);  /* 等速回転 */
}

#start:checked ~ #base1 #base2 #button .stop-l {
  visibility:visible;
}

#start:checked ~ #base1 #base2 #button #start-l {
  visibility:hidden;
}

/* ストップ */

.stop:checked ~ #base1 #base2 #reset #board {
  /* 減速 */
  --theta2:calc(var(--decel-t) * 60);
  transition:--theta2 calc(var(--decel-t) * 1s) cubic-bezier(0.3333333, 0.6666667, 0.6666667, 1);
}

.stop:checked ~ #base1 #base2 {
  animation:disable2 calc(var(--decel-t) * 1s + 1s) step-start,  /* 減速中 入力ディスエーブル */
            decided 1s steps(9, jump-both) calc(var(--decel-t) * 1s) forwards;  /* 確定表示 */
}

#stop-1:checked ~ #base1 #base2 {
  --decel-t:16;
}
#stop-2:checked ~ #base1 #base2 {
  --decel-t:18;
}
#stop-3:checked ~ #base1 #base2 {
  --decel-t:20;
}
#stop-4:checked ~ #base1 #base2 {
  --decel-t:22;
}
#stop-5:checked ~ #base1 #base2 {
  --decel-t:24;
}

/* 確定表示 */

#dec1, #dec2 {
  visibility:var(--dec-vis);

  transform-origin:0 120px;
  --round:calc((var(--theta1) + var(--theta2)) / var(--sector-angle));  /* 四捨五入 */
  transform:rotate(calc((var(--theta1) + var(--theta2) - var(--round) * var(--sector-angle)) * 1deg));
}

#dec1 {
  position:absolute;
  left:120px;
  top:0;
  width:120px;
  height:240px;
  clip-path:var(--sector-clip);
}

#dec1-2 {
  position:absolute;
  left:0;
  top:-2px;
  width:122px;
  height:244px;
  background-color:red;
  clip-path:circle(121.5px at 0 122px);
}

#dec2 {
  position:absolute;
  left:120px;
  top:0;
  width:120px;
  height:240px;
  pointer-events:none;
}

#dec2-2, #dec2-3 {
  position:absolute;
  left:0;
  top:119px;
  width:121px;
  height:2px;
  background-color:red;
  transform-origin:0 1px;
}

#dec2-2 {
  transform:rotate(calc(var(--sector-angle) / 2 * -1deg));
}

#dec2-3 {
  transform:rotate(calc(var(--sector-angle) / 2 * 1deg));
}

-->
</STYLE>

</HEAD>

<BODY>
<BR>
<DIV ID="title">スタイルシート ルーレット</DIV>
<BR>

<INPUT TYPE=RADIO NAME="button-g" ID="start">
<INPUT TYPE=RADIO NAME="button-g" ID="stop-1" CLASS="stop">
<INPUT TYPE=RADIO NAME="button-g" ID="stop-2" CLASS="stop">
<INPUT TYPE=RADIO NAME="button-g" ID="stop-3" CLASS="stop">
<INPUT TYPE=RADIO NAME="button-g" ID="stop-4" CLASS="stop">
<INPUT TYPE=RADIO NAME="button-g" ID="stop-5" CLASS="stop">

<DIV ID="base1">
<DIV ID="base2">

選択肢数<BR>
<INPUT TYPE=RADIO NAME="choices-g" ID="n-2" TABINDEX="-1" CLASS="disable1" CHECKED><LABEL FOR="n-2" CLASS="disable1">2個</LABEL>
<INPUT TYPE=RADIO NAME="choices-g" ID="n-3" TABINDEX="-1" CLASS="disable1"><LABEL FOR="n-3" CLASS="disable1">3個</LABEL>
<INPUT TYPE=RADIO NAME="choices-g" ID="n-4" TABINDEX="-1" CLASS="disable1"><LABEL FOR="n-4" CLASS="disable1">4個</LABEL>
<INPUT TYPE=RADIO NAME="choices-g" ID="n-5" TABINDEX="-1" CLASS="disable1"><LABEL FOR="n-5" CLASS="disable1">5個</LABEL>
<BR>
<INPUT TYPE=RADIO NAME="choices-g" ID="n-6" TABINDEX="-1" CLASS="disable1"><LABEL FOR="n-6" CLASS="disable1">6個</LABEL>
<INPUT TYPE=RADIO NAME="choices-g" ID="n-7" TABINDEX="-1" CLASS="disable1"><LABEL FOR="n-7" CLASS="disable1">7個</LABEL>
<INPUT TYPE=RADIO NAME="choices-g" ID="n-8" TABINDEX="-1" CLASS="disable1"><LABEL FOR="n-8" CLASS="disable1">8個</LABEL>
<BR>

<DIV ID="reset">
<DIV ID="board" CLASS="disable1">
<DIV ID="rim">

<DIV ID="dec1">
<DIV ID="dec1-2"></DIV>
</DIV>

<DIV ID="back">
<INPUT TYPE=TEXT ID="choice1" TABINDEX="-1" PLACEHOLDER="選択肢を入力" CLASS="choice">
<INPUT TYPE=TEXT ID="choice2" TABINDEX="-1" PLACEHOLDER="選択肢を入力" CLASS="choice">
<INPUT TYPE=TEXT ID="choice3" TABINDEX="-1" PLACEHOLDER="選択肢を入力" CLASS="choice">
<INPUT TYPE=TEXT ID="choice4" TABINDEX="-1" PLACEHOLDER="選択肢を入力" CLASS="choice">
<INPUT TYPE=TEXT ID="choice5" TABINDEX="-1" PLACEHOLDER="選択肢を入力" CLASS="choice">
<INPUT TYPE=TEXT ID="choice6" TABINDEX="-1" PLACEHOLDER="選択肢を入力" CLASS="choice">
<INPUT TYPE=TEXT ID="choice7" TABINDEX="-1" PLACEHOLDER="選択肢を入力" CLASS="choice">
<INPUT TYPE=TEXT ID="choice8" TABINDEX="-1" PLACEHOLDER="選択肢を入力" CLASS="choice">
</DIV>

</DIV>

<DIV ID="dec2">
<DIV ID="dec2-2"></DIV>
<DIV ID="dec2-3"></DIV>
</DIV>

<DIV ID="pointer"></DIV>
</DIV>
</DIV>

<DIV ID="button">
<LABEL ID="start-l" FOR="start">スタート</LABEL>
<LABEL ID="stop-1-l" FOR="stop-1" CLASS="stop-l">ストップ</LABEL>
<LABEL ID="stop-2-l" FOR="stop-2" CLASS="stop-l">ストップ</LABEL>
<LABEL ID="stop-3-l" FOR="stop-3" CLASS="stop-l">ストップ</LABEL>
<LABEL ID="stop-4-l" FOR="stop-4" CLASS="stop-l">ストップ</LABEL>
<LABEL ID="stop-5-l" FOR="stop-5" CLASS="stop-l">ストップ</LABEL>
</DIV>

</DIV>
</DIV>

</BODY>

</HTML>