プログラムが自分の思う通りに動作した時、バグ(不具合)の原因が分かった時は嬉しいものです。まさにプログラマ冥利に、尽きました。その思いが強くて会社を辞めた後もプログラムを作りたいという気持ちに駆られました。
丁度その頃(会社を辞める前か辞めた頃)HTML,CSS,javascript を使用したホームページを作ることが主流になってきました。その後、十年以上HTML,CSS,javascriptの勉強をしています。
2022冬季北京オリンピックの感動も冷めやらぬ中、CSS と javascript を使用して3Dアニメーションを作ってみました。
設定をご自由に変更して「RUN」ボタンをクリックして試みてください。面白いですよ!
http://hilbert314159.org/3Danimation/
hilbert314159.org
このアプリを作成するにあたってのポイント
・ボタンをクリックされたらアニメーションを開始するには、どうするの?
・えっ!本当。CSSの中で変数を使用できるの?
・javascriptを使用してキーフレーム(keyframe)の引数を変更するには、どうするの?
などの技術的な内容を記述します。
今まで HTML,CSS,javascript を使用してWEBアプリを作る時には、コードエディター「brackets」を使っていたのですが、サポートが終了したとのことでしたので、「Visual Studio Code」へ移行したいと思っていました。簡易的なローカルサーバ「Live Server」をインストールして試してみましたがエディターで変更した内容がbracketsの様に、すぐにはブラウザに反映されないので未だ拡張機能(プラグイン)が足りないのかなと思っていました。そんな時ファイル・メニューの中に「自動保存」の項目があることに気づき「これかも知れない」と思い、「自動保存」にチェックをしたところ、エディターで変更した内容が即時にブラウザに反映される様になりました。自動保存の設定項目は「off」「afterDelay」「onFocusChane」「onWindowChange」があります。
2. アニメーションの作り方とアニメーションを開始する方法
2.1 アニメーションの作り方
アニメーションの始め方の前に、アニメーションの作り方を簡単に説明します。
どの様なアニメーションを作るのか、アニメーションのスムーズなトランジション(移り変わり、変遷)の開始点と終了点を
定義する描画をキーフレーム(keyframe)を作ります。例えば、画像を右に移動してから90度時計回りに回転させたい場合には
@keyframes mov_rot {
0% { transform: translateX(0px) rotate(0deg);}
50% { transform: translateX(100px) rotate(0deg);}
100% { transform: translateX(100px) rotate(90deg);}
}
と記述します。
「transformプロパティ」を使えば、要素に動きをつけることができます。移動、回転、伸縮、傾斜の4つの効果が用意されてあり、二次元的な動きだけではなく、三次元的な動きまでも可能にしているのが特徴です。
transformプロパティは,トランスフォーム関数を指定して対象要素を変形させます。
【平面空間】
関数 |
効果 |
none |
要素を変形しません。 |
matrix() |
行列式によって要素を変形します。 |
translate() |
要素のxy座標を移動します。 |
translateX() |
要素のx座標を移動します。 |
translateY() |
要素のy座標を移動します。 |
scale() |
要素をx軸,y軸方向に拡大・縮小します。 |
scaleX() |
要素をx軸方向に拡大・縮小します。 |
scaleY() |
要素をy軸方向に拡大・縮小します。 |
rotate() |
要素を回転します。 |
skew() |
要素の形状をx軸,y軸方向に傾斜します。 |
skewX() |
要素の形状をx軸方向に傾斜します。 |
skewY() |
要素の形状をy軸方向に傾斜します。 |
【3D空間】
関数 |
効果 |
none |
要素を変形しません。 |
matrix3d() |
行列式によって要素を変形します。 |
translate3d() |
要素のxyz座標を移動します。 |
translateZ() |
要素のz座標を移動します。 |
scale()3d() |
要素をx軸,y軸,z軸方向に拡大・縮小します。 |
scaleZ() |
要素をz軸方向に拡大・縮小します。 |
rotateX() |
要素をx軸を中心に回転します。 |
rotateY() |
要素をy軸を中心に回転します。 |
rotateZ() |
要素をz軸を中心に回転します。 |
perspective() |
画面から視点の距離を指定して,z軸方向に変形した要素の奥行を表します。 |
アニメーションを開始する方法として、よく使用する疑似クラスに
疑似クラス |
イベント |
active |
ユーザーの操作により、要素がアクティブになった時にアニメーションを開始する。 |
hover |
ユーザーの操作により、要素にカーソルなどが乗った時にアニメーションを開始する。 |
等があります。
画像がホーバー(画像にカーソルなどが乗った)時にアニメーションを開始するには
.rect_part3:hover {
animation-name: mov_rot;
animation-duration: 1s;
animation-fill-mode: forwards;
animation-timing-function: ease;
animation-iteration-count: 1;
}
ここで各プロパティの役割を説明します。
プロパティ |
内容 |
animation-name |
アニメーションを適用する要素を指定する。 |
animation-duration |
アニメーションが完了するまでの時間を指定する。 |
animation-fill-mode |
アニメーションの再生中・再生後のスタイルを指定する。 |
animation-timing-function |
アニメーションの進行度を指定する。 |
animation-iteration-count |
アニメーションの実行回数を指定する。 |
さらに animation-timing-function, animation-fill-mode プロパティの詳細について述べると
animation-timing-function プロパティは、アニメーションが変化する速度を指定します。
値 |
進行度 |
ease |
アニメーションの開始・終了付近の動きを滑らかにします。 |
linear |
一定の割合で直線的に再生します。 |
ease-in |
アニメーションの開始付近の動きを穏やかにします。 |
ease-out |
アニメーションの終了付近の動きを穏やかにします。 |
ease-in-out |
アニメーションの開始・終了付近の動きを穏やかにします。 |
cubic-bezier() |
三次ベジェ曲線の軌跡によってアニメーションの進行度を指定します。 |
step-start |
アニメーションの開始時点で終了状態となります。 |
step-end |
開始時点では変化せず、終了時にアニメーションが完了した状態になります。 |
steps() |
指定したステップ数で等分に区切ります。 |
animation-fill-mode プロパティは、アニメーション再生中・再生後のスタイルを指定します。
値 |
スタイル |
none |
スタイルを指定します。アニメーション再生後は、元のスタイルが適用されます。animation-delayプロパティを指定している場合、再生までの時間は元のスタイルが適用されます。 |
backwards |
アニメーション再生後は、最初のキーフレーム(0%)のスタイルが適用されます。animation-delayプロパティを指定している場合、再生までの時間は最初のキーフレーム(0%)のスタイルが適用されます。 |
forwards |
アニメーション再生後は、最後のキーフレーム(100%)のスタイルが適用されます。 animation-delayプロパティを指定している場合、再生までの時間は元のスタイルが適用されます。 |
both |
アニメーション再生後は、最後のキーフレーム(100%)のスタイルが適用されます。 animation-delayプロパティを指定している場合、再生までの時間は最初のキーフレーム(0%)のスタイルが適用されます。 |
但し、animation-delayプロパティはアニメーションが開始するまでの時間を指定するプロパティです。
ユーザー操作によりボタンをクリックされた時にアニメーションを開始するためにはjavascriptを使用する必要があります。
ユーザー操作によりボタンをクリックされた時、javascriptの関数を呼び出すためはイベント処理を実行するためのメソッド addEventLListener() を使用します。
let Element = document.getElementById('クラス名など');
Element.addEventListener('click', 関数名);
と記述します。ただし関数名の後に () を付ける必要はありません.
イベントの種類には
【マウス関連】
イベント |
発生のタイミング |
click |
ボタンをクリックしたとき |
mousemove |
カーソルがターゲット内に移動したとき |
mouseover |
カーソルがターゲット内に侵入してきたとき |
mousedown |
ボタンを押下したとき |
mouseup |
ボタンを離したとき |
mouseout |
カーソルがターゲットの外に出たとき |
【キーボード関連】
イベント |
発生のタイミング |
keypress |
キーを押して離したとき |
keydown |
キーを押下したとき |
keyup |
キーを離したとき |
【DOM関連】
イベント |
発生のタイミング |
DOMFocusin |
ターゲットがフォーカスを受け取ったとき |
DOMFocusout |
ターゲットがフォーカスを失ったとき |
DOMActivate |
ターゲットがアクティブになったとき |
【INPUT関連】
イベント |
発生のタイミング |
select |
テキストフィールドで文字が選択されたとき |
change |
コントロールの値が変化した後 |
submit |
submitボタンが押されたとき |
reset |
resetボタンが押されたとき |
focus |
コントロールがフォーカスを受け取ったとき |
blur |
コントロールがフォーカスを失ったとき |
などがあります。特にアニメーションに関連するイベントは
イベント |
発生のタイミング |
animationstart |
アニメーションを開始したときに発生 |
animationiteration |
アニメーションを反復して実行するときに発生 |
animationend |
アニメーションが完了したときに発生 |
animationcancel |
アニメーションを途中でキャンセルしたときに発生 |
があります。
2.2 アニメーションを開始する方法
メソッド addEventListener により呼び出された関数の中で、アニメーションを開始します。ここで classList について説明します。
classList とは特定の要素のクラス名を追加したり、削除したり、参照したりすることが出来るプロパティです。
classListの後にメソッドを定義することにより、追加削除などの機能を指定することができます。
主な classList のメソッドは
メソッド |
機能 |
add |
クラスを追加する |
remove |
クラスを削除する |
contains |
クラスが含まれているか確認する |
toggle |
クラスが含まれていれば削除、含まれていなければ追加する。 |
があります。
そこでホーバー疑似クラスの時に作った様にしてアニメーションのクラスを作成します。
.rect_rotate {
animation-name: mov_rot;
transform-style: preserve-3d;
animation-duration: 1s;
animation-fill-mode: forwards;
animation-timing-function: ease;
animation-iteration-count: 1;
}
このアニメーションのクラスを画像などのクラスに追加することにより、アニメーションを開始することができます。そしてアニメーションが終了したならば、アニメーションが完了したときに発生するイベントによりアニメーションのクラスを忘れずに削除します。
3. CSSの中で変数を使用する手順
もう一つ特記したい事は、今までは知らなかったのですが CSS の中で変数が使用できるという事です。カスタム・プロパティという名称で呼ばれているそうです。(2015年にW3Cから勧告されたの事です。)これは大変便利な機能です。WEBサイトやWEBアプリの制作過程においてヘッダー、ナビゲーション、セクション、フッターなどの全ての幅(width)を少しだけ広げたいという事はよくありました。この様な場合 CSS の中の最初に変数を定義しておけば、一か所を変更するだけで全ての幅を変更することができます。
変数名の先頭に二つのハイフンを付けて変数を定義しておき、変数を使用するときにはvar()関数に変数名を代入します。
さらに、:root 疑似クラスを使って
:root {
--bodywidth: 720px;
}
と定義すれば、HTML文書の全体にわたって適用することができます。
このカスタム・プロパティを使用する、もう一つのメリットはキーフレームの中に変数を使えば、javascript により変数を変更することができます。たとえばアニメーションを回転させるキーフレームを
@keyframes Rotate_rectangle {
from{
transform: rotateX(0deg) rotateY(0deg) rotateZ(0deg);
}
to{
transform: rotateX(var(--val-xdeg)) rotateY(var(--val-ydeg)) rotateZ(var(--val-zdeg));
}
}
と定義しておけば、javascript の setProperty() メソッドにより変更することができます。
function setProperty_xdeg(event){
var xdeg = event.currentTarget.value + "deg";
document.documentElement.style.setProperty('--val-xdeg', xdeg);
}