Adobe XDの無料UIキットページからダウンロードしたAuto-Animate(解凍後のファイル名はxd-resources-auto-animate-ui.xd)に、スロット風に数字が回転されて表示されるアニメーションがありました。
そこから発想を得て、今日の年月日をスロット風に表示してみました。
おおまかな流れは、まずJavaScriptで今日の日付を取得し一文字ずつに分解します。
そして、jQueryの$.eachメソッドの中にfor文を入れて各数字をHTMLの該当箇所に挿入していきます。
CSSの方では、挿入された数字を縦に並べ、上方向へ移動するアニメーションをつけます。
因みにスロットの数字が並べられた回転するアレは「リール」というそうです。
コメントアウトに「リール」という言葉が出てきますので念のため。
各数字の回転アニメーションを同時に終了させる
CODEPEN
「Run Pen」をクリックしてください。右下の「Rerun」で再生できます。
See the Pen date slot display in order at the same time by blue moon (@blue-moon) on CodePen.
HTML
1文字ずつに分割した数字を挿入するタグには、IDを割り当てています。
但し、2100年以降は考慮していないため西暦の1桁目と2桁目箇所にはIDは割り当てず、今日の数字の前のリールに並ぶ0~9の数字は最初からHTMLに入れています。
<body>
<div class="counter">
<div class="year">
<div class="fix-number">
<span>0</span><span>1</span><span>2</span><span>3</span><span>4</span><span>5</span><span>6</span><span>7</span><span>8</span><span>9</span><span>0</span><span>1</span><span>2</span>
</div>
<div class="fix-number">
<span>0</span><span>1</span><span>2</span><span>3</span><span>4</span><span>5</span><span>6</span><span>7</span><span>8</span><span>9</span><span>0</span>
</div>
<div id="change-number-1" class="change-number"></div>
<div id="change-number-2" class="change-number"></div>
</div>
<div class="month">
<div id="change-number-3" class="change-number"></div>
<div id="change-number-4" class="change-number"></div>
</div>
<div class="date">
<div id="change-number-5" class="change-number"></div>
<div id="change-number-6" class="change-number"></div>
</div>
</div>
</body>
CSS
body {
background: #010353;
font-family: sans-serif;
font-size: 50px;
font-weight: 700;
line-height: 1.6;
color: #ff53c3;
}
.counter {
display: flex;
width: fit-content;
margin: 50px auto;
}
.counter > div {
margin: 0 8px;
width: fit-content;
height: 76px;
display: flex;
overflow-y: hidden; /* 各リールに数字は縦に長く並ぶが、表示は1文字のみ */
}
.fix-number,
.change-number {
width: 52px;
height: fit-content;
display: flex;
flex-direction: column; /* スロットのリールに数字を縦に並べる */
/* アニメーションは1回、弾むように始まり弾むように終わり、最後の状態をキープ */
animation: displayAnim 3s cubic-bezier(0.55, -0.17, 0.74, 1.29) forwards;
}
/*
* リールをY方向に移動するアニメーション
* アニメーション最後の位置は、最後の数字の高さ分下げる
* font-size: 50px; line-height: 1.6; より、50px × 1.6 = 80px と算出
*/
@keyframes displayAnim {
0% { transform: translateY(0%); }
100% { transform: translateY(calc(-100% + 80px)); }
}
span {
display: inline-block;
text-align: center;
}
JS
$(document).ready(function () {
// 今日の年月日を取得
const today = new Date();
const yearNum = today.getFullYear();
const monthNum = today.getMonth() + 1;
const dateNum = today.getDate();
//分割するため一旦文字列に変換
const yearSt = String(yearNum); //西暦
const monthSt = String(('0' + monthNum).slice(-2)); //月の前に0を付け足し後ろから2文字を取得
const dateSt = String(('0' + dateNum).slice(-2)); //日の前に0を付け足し後ろから2文字を取得
// 取得した年月日を1文字ずつに分割し数値に変換
const yearNum3 = Number((yearSt).slice(2, 3)); //西暦の3桁目
const yearNum4 = Number((yearSt).slice(3, 4)); //西暦の4桁目
const monthNum1 = Number((monthSt).slice(0, 1)); //月の1桁目
const monthNum2 = Number((monthSt).slice(1, 2)); //月の2桁目
const dateNum1 = Number((dateSt).slice(0, 1)); //日の1桁目
const dateNum2 = Number((dateSt).slice(1, 2)); //日の2桁目
// 数字を代入する要素を全て取得
const changeNum = $('.change-number');
//0~9の数字をスロットの各リールに追加
const beforeNum = '<span>0</span><span>1</span><span>2</span><span>3</span><span>4</span><span>5</span><span>6</span><span>7</span><span>8</span><span>9</span>';
changeNum.each(function () {
$(this).append(beforeNum);
});
// 今日の日付を分割した数字のオブジェクトを用意(上記の数字の後に追加するもの)
const obj = {
1: yearNum3,
2: yearNum4,
3: monthNum1,
4: monthNum2,
5: dateNum1,
6: dateNum2,
}
// スロットの各リールに今日の日付の数字が最後になるまで数字を追加していく
$.each(obj, function (key, val) {
for (let i = 0; i < val + 1; i++) {
$("#change-number-" + key).append(`<span>${i}</span>`);
}
});
});
日付の1桁目が数字の9の場合、HTMLは下記のように出力されます。
各数字の回転アニメーションを順番に終了させる
CODEPEN
「Run Pen」をクリックしてください。
See the Pen date slot display in order by blue moon (@blue-moon) on CodePen.
CSS
CSSのみ下記を追記変更しています。
.fix-number,
.change-number {
width: 52px;
height: fit-content;
/* アニメーション時間は個別に設定するため、durationを削除 */
animation: displayAnim cubic-bezier(0.55, -0.17, 0.74, 1.29) forwards;
display: flex;
flex-direction: column;
}
.fix-number:nth-child(1) {
animation-duration: 2.85s;
}
.fix-number:nth-child(2) {
animation-duration: 2.9s;
}
.year .change-number:nth-of-type(3) { /* 兄弟要素の中で3番目 */
animation-duration: 2.95s;
}
.year .change-number:nth-of-type(4) { /* 兄弟要素の中で4番目 */
animation-duration: 3s;
}
.month .change-number:nth-child(1) {
animation-duration: 3.05s;
}
.month .change-number:nth-child(2) {
animation-duration: 3.1s;
}
.date .change-number:nth-child(1) {
animation-duration: 3.15s;
}
.date .change-number:nth-child(2) {
animation-duration: 3.2s;
}