CSS3とHTML5 Canvasで作るモーショングラフィック
ICS MEDIAリニューアル後のトップページに掲載しているモーショングラフィック。これはCSS3とHTML5 Canvas要素を使って作成したものです。時間経過とともに波の形状と色彩が変化し、多彩な表現を楽しめるようになっています。
本記事ではCSS3とHTML5 Canvasの理解につながることを目標に、このモーショングラフィックの作成方法をステップ形式で解説します。サンプルのソースコードは全てGitHubにて公開していますので、あわせて参照ください。
▲ 完成版サンプル。実装する上で重要な表現のエッセンスだけを絞って解説していきます。
ステップ1. CSS3でグラデーション背景の作成
まずはベースとして時間経過で色彩が変化するグラフィックを作成しましょう。CSS3で縦に長いグラデーションの背景を用意し、CSSアニメーションを使って縦方向に移動させることでグラデーションが変化する表現ができあがります(ステップ1のソースコード)。
#bg { /* 背景グラデーションの作成 */ background: linear-gradient(to bottom, hsl(180, 80%, 40%), hsl(240, 80%, 60%), hsl(300, 80%, 40%)); background-size: 400% 400%; animation: AnimationName 10s ease infinite; } @keyframes AnimationName { 0% { background-position: 50% 0% } 50% { background-position: 50% 100% } 100% { background-position: 50% 0% } }
ステップ2. 波のモーショングラフィックを描く
波のモーショングラフィックは、HTML5 Canvasで描いています。フレームワークとしてCreateJSとProcessing.jsを使っています。作り方は「FrocessingではじめるActionScriptドローイング|gihyo.jp」で紹介されているので参考になるでしょう(別の言語ですが、Action Script 3.0とJSと似ているので参考になります)。ポイントとしてはランダム関数として離散乱数が得られるMath.random()
ではなく、連続した乱数(パーリンノイズ)が得られるProcessingのnoise()
関数を使って曲線の頂点を計算していることです(波の表示クラスのコード)。
// 波の次の目標値を計算 for (let i = 0; i <= vertexNum; i++) { // 乱数を取得、-0.5〜+0.5の範囲 let noiseNum = noise(i * 0.2, this.time + timeOffset) - 0.5; // 目標座標を計算。画面の高さに比例 let targetY = noiseNum * stageH * 2; // イージングの公式を使って、頂点座標をなめらかに変化させる vertexArr[i] += (targetY - vertexArr[i]) * 0.05; }
ステップ3. 波に残像を加える
Canvas要素は直前の描画結果を引き継ぐという処理が可能です。この方法を使えば残像効果を実装することができます。詳しくは月刊誌Web Designing 2015年6月号の連載「応用講座Flash for HTML5」にて解説しましたので参考ください。ステップ2で作成した波の表現に残像効果を加えてみましょう。
残像効果は具体的には次のコードで実装することができます(ステップ3のコード)。
// 薄く暗く塗る var context = stage.canvas.getContext("2d"); context.fillStyle = "rgba(0, 0, 0, 0.2)"; // 4番目の透明度がポイント context.fillRect(0, 0, 幅, 高さ); // 表現を更新 stage.update();
ステップ4. 照明効果を作成する
今までのステップとは別に、演出を華やかにするために一部分だけ光があたっているような演出をCanvas要素で作成しましょう。円形グラデーションの円を2つ配置して、左右に動かします。周期的な動きを作るには三角関数を使うと便利でしょう(ステップ4のコード)。
// 円のX座標 (左右に周期的に移動させる) var dx = w * 1 / 3 + w / 10 * Math.sin(Date.now() / 4000); // 円のY座標 var dy = h * 1 / 3; // 円の大きさ var size = w / 2;
ステップ5. 波と照明効果を合算する
ステップ3とステップ4で作成した表現を合成します。輝度(ルミナンス)だけで合成したいので、Canvas要素のglobalCompositeOperation
プロパティーをlighter
に設定してdrawImage()
メソッドで合成します(ステップ5のコード)。
// 2つのステージを合成する var ctx = 照明のステージ.canvas.getContext("2d"); ctx.globalCompositeOperation = "lighter"; ctx.drawImage(波のステージ.canvas, 0, 0);
ステップ6. グラデーション背景と合成
最後にステップ1とステップ5の表現を合成します。記事「CSS3のブレンドモードmix-blend-modeを使いこなそう」で紹介したようにCSS3のmix-blend-mode
プロパティーを用い特殊なブレンドモードとしてHTML要素を重ねあわせます。これで完成です!(ステップ6のコード)
#canvasOverlay { mix-blend-mode: hard-light; }
ここまでの手順を図解すると次のようになります。一つ一つのステップは単純ななものですが、どうやって合成するかがポイントであったかがわかります。
まとめ
いかがでしたでしょうか? 仕組みがわかれば意外とシンプルなものです。ブレンドモードとして利用しているCSS3のmix-blend-mode
プロパティーと、Canvas要素のglobalCompositeOperation
プロパティーの両方を使えばHTML5での表現の幅が広がります。
いきなりコードで実現するのが難しいという方はPhotoshop等の画像加工ソフトで試してから、コードで実装するとイメージしやすいと思います。ぜひみなさんもWebでのモーショングラフィックに挑戦してみてください。