どうも、フロントエンドエンジニアの田島です。
弊社カヤックでは、2016年の7月7日を以て3年ぶりのコーポレートサイトリニューアルを行いました。
今回のサイトの大きなテーマは、 5種類のデザインから自分の好きなテーマに切り替えて楽しめる ということです。
現在のカヤックのアイデンティティを示す5つのテーマ、 「Simple」「Manga」「Game」「Tech」「Kamakura」 に則り、それぞれのテーマに応じたデザイン・演出を実装しています。
本記事では、フロントエンド実装に当たって工夫した、
- 開発環境
- CSS/JavaScript の設計
- 『餅は餅屋』 大作戦
- その他Tips, 使用したライブラリ
というトピックについて、書いていきたいと思います。
開発環境
本サイトではRuby on Railsを採用しています。 フロントエンド側でもなるべくrailに乗っかるべく、gulp等のタスクランナーを使う場面は極力抑え、asset pipelineベースで開発を進めました。
JavaScriptはES6を使いたかったため、 browserify-rails + babelify という構成としました。 こちらの導入手法をおさらいしますと、
まずbrowserify-railsというgemをインストールし、
[Gemfile]
gem 'browserify-rails'
npm moduleであるbabel-preset-es2015とbabelifyをインストールした上で、
npm install babel-preset-es2015 babelify --save-dev
config/application.rb 内でbrowserify_railsのオプションとしてbabelifyを用いるように記述します。
[config/application.rb]
config.browserify_rails.commandline_options = "-t [ babelify --presets [ es2015 ] ]"
これで、asset pipeline上のJavaScriptはES6として記述していくことができます。importも使い放題ですね。
さらに、フロントエンドエンジニアとしてはどうしても欲しいlivereload機能ですが、今回はbrowser-syncを使うことで解決しました。
つまり、browser-syncをインストールした上で、
npm install browser-sync --save-dev
npm startコマンドでそれを立ち上げるようにします。この際、立ち上げるサーバーではrailsが立てられているlocalhost:3000をproxyしています。 こうすることで、railsのapp内でファイルが変更される度にブラウザを自動更新してくれます。
[package.json]
"scripts": {
"start": "browser-sync start --proxy localhost:3000 --files 'app/assets/stylesheets/*.scss, app/assets/javascripts/**/*.js, app/views/**/*'"
}
開発時には、 bundle exec rails server でrailsサーバーを立ちあげてから、 npm start でbrowser-syncのサーバーを立てるかたちになります。 ブラウザ上ではlodalhost:3001で確認しながら開発を進めていきます。
CSSの設計
レスポンシブ対応
本サイトではPC用サイト / スマホ用サイトをレスポンシブで出し分けています。 出し分け方として、media queryを使って読み込むCSSファイル自体を変更する手法 をとりました。 大規模サイトで、特にsassの@extendを多用する設計になっている場合、PCサイトとスマホサイトのCSSを同時に記述していくと、同一セレクタ上での予期せぬstyleのバッティングが頻発するため、思い切ってファイル自体を分けるやり方はオススメです。
<link rel="stylesheet" media="print, screen and (min-width: 801px)" href="#{PC用サイトCSS}" />
<link rel="stylesheet" media="screen and (max-width: 800px)" href="#{スマホサイト用CSS}" />
テーマ切り替え
今回のサイトの核となる、テーマ切り替えのCSS設計は以下の様にbodyに対してdata属性を付与する手法をとりました。 テーマを切り替える際にはここだけ変更すれば良いので、管理は非常にシンプルとなります。
body[data-design="simple"]{
@content;
}
sass上での設計方法としては、以下のようにテーマごとのmixinを予め用意しておいた上で、
@mixin simple-design{
body[data-design="simple"]{
@content;
}
}
@mixin comic-design{
body[data-design="comic"]{
@content;
}
}
@mixin game-design{
body[data-design="game"]{
@content;
}
}
@mixin kamakura-design{
body[data-design="kamakura"]{
@content;
}
}
@mixin tech-design{
body[data-design="tech"]{
@content;
}
}
テーマ別にデザインの差異があるモジュール部分にて、下記のようにstyleを上書きしていくやり方をとりました。
// 基本style
.block{
color: #fff;
}
// テーマ別のデザイン差異
@include simple-design{
.block{
color: #f00;
}
}
@include comic-design{
.block{
color: #ff0;
}
}
JavaScriptの設計
本サイトでは右下にある切り替えボタンから、サイトのテーマを変更することができます。 実装面では、CSSの変更だけでなく、演出を担っているJavaScriptも実行中の処理を変更しなければなりません。
テーマ切り替えのためのイベント管理にはEventEmitterを採用しました。
以下のようにDesignManagerというクラスを作っておき、デザイン切り替えボタンが押されるとsetDesignが呼ばれ、CSSの切り替え(bodyのdata-design属性変更)を行った上で、切り替えイベントを発行しています。 イベントの中身には、変更前・変更後のテーマ名が渡されます。
import EventEmitter from 'events';
const DATA_DESIGN = 'data-design';
class DesignManager extends EventEmitter{
constructor(){
super();
this.currentDesign = null;
}
setDesign(design){
const currentDesign = this.currentDesign;
if (design === currentDesign) {
return;
}
$('body').attr(DATA_DESIGN, design);
this.currentDesign = design;
// テーマ切り替えイベントを発行
this.emit('change', {
from: currentDesign,
to: design
});
}
};
(※実際のプログラムから一部抜粋)
例えば、GAMEテーマの背景を動かしている演出は、下記のようにdesignManagerのイベントを監視しながら、
・切り替え先がGAMEである場合は演出開始 ・切り替え元がGAMEである場合は演出停止
という書き方をします。 これが、テーマごとに実行すべきJavaScriptの処理を制御するための基本設計です。
[GameBackground.js]
const gamecBackground = new GameBackground();
const GAME_NAME = 'game';
designManager.on('change', (e) => {
if(e.to === GAME_NAME){
gameBackground.start();
}
else if(e.from === GAME_NAME){
gameBackground.stop();
}
}
『餅は餅屋』 大作戦
今回のカヤックサイトの演出部分は、カヤック社員の持てるスキルを総動員する形で実装しました。 アニメーション制作を得意とする人、音制作を得意とする人、ジェネラティブなプログラミングを得意とする人、クイズを考えるのが得意な人など、様々な種類のクリエイターを抱えるカヤックならではの特徴を活かした、『餅は餅屋』的な作り方を意識しました。
具体例を紹介していきましょう。
GAMEテーマのフッターにいるキャラクター
GAMEテーマのフッターで流れているキャラクターの動きは、ゲームチームにいるアニメーターが制作し、フロントエンドエンジニアである私がコーディングに落としこむという流れをとりました。 例えば、Adobe Animateで作成したキーフレームアニメーションをCSSのkeyframesに書き起こしたり、 Spriterで作成した連番画像アニメーションをSprite化してJavaScriptで再生する、という作り方をしています。
採用フォームでのチャット風インターフェース
スマートフォンから採用フォーム画面に進むと、チャット風のインターフェースになる仕掛けを施しました。 チャット感覚でサクサクとエントリーできるだけでなく、会話相手となるBOTが時折気の利いたことを言うことで楽しませる工夫をしています。
例えば、誕生日を入れるとその日が何の日か教えてくれてたり、電話番号を入力すると、勝手に語呂合わせしてくれたり。
それぞれの辞書データの作成は、弊社の謎かけを得意とするディレクターや、クイズ作りを得意とするプロデューサに頼んで手伝っていただきました。
TECHテーマのロゴ演出・背景演出
TECHテーマではWebGLを多く利用しています。
例えば、左上のロゴが3Dになっていたり、
背景ではシェーダーを使ったジェネラティブな動きを取り入れています。
いずれも、Blenderでの3Dモデル制作を得意とするデザイナー、普段openFrameworksやUnityでシェーダーを書いているエンジニアに依頼して制作しています。
その他Tips, 使用したライブラリ
閲覧環境のスペックに応じて演出のレベルをコントロールする仕組み
本サイトでは、上記のように多くの演出を盛り込んでいますが、あくまでコーポレートサイトであるため幅広いユーザに閲覧されることが想定されます。 従って、比較的処理性能の低いマシンから閲覧された場合には演出のレベルを落として負荷を下げなければなりません。
対処方法として、requestAnimationFrameを使ってFPS値を監視し、 閾値を下回っていたら演出レベルを段階的に下げる という処理を行っています。 これは、マシンスペックを要する演出系サイトにおいては汎用的に使いまわすことのできる手法です。
音声はboombox.jsを採用
GAMEテーマとTECHテーマでは各所でサウンドエフェクトを実装しています。 音声再生のライブラリとして、boombox.jsを採用しました。
このライブラリを用いる主なメリットとして、 Audio Sprite機能が挙げられます。 特にSEを多用する場合では、音声データをバラバラに用意しておくと読み込むファイル数が膨れ上がり、フロントエンド的にもサーバーサイド的にも負荷が高くなります。 Audio Spriteを使えばファイル数は1つで済むため、リクエスト数の削減にもなりますし、フロントエンド側でプリロードの管理に意識を割かなくて良いため非常に楽になります。
CSSのmix-blend-mode
CSSプロパティとして採用したモダンなやつだと、mix-blend-modeがあります。 これは、CSSだけでphotoshopのようなレイヤー合成ができちゃうというスグレモノです。 今回は、乗算合成をkamakuraテーマのフッターにいるイラストに対して用いています。 こうしてON/OFFを比べて見ると違いがよくわかりますね。背景となじませたいときに今後も重宝するでしょう。 IEはまだ未サポートだったりしますが、必須ではない付加演出の場面であれば、積極的に使っていきたいです。
フォント・アイコンデータ
テーマごとに全てフォントファミリーも変えています。 今回は、欧文フォントにGoogle Fontsを、日本語フォントにはType Squareを利用しています。 フォントデータを自前サーバーでホスティングする必要がないため楽です。
さらに、アイコン素材系のほとんどはFont Awesomeを利用しています。 矢印やSNSアイコンなどよく使われるやつは一通りそろっています。こちらも素材をホスティングする必要がなく、アイコンをフォントデータ的に使うことができて非常に便利でした。
おわりに
カヤックのコーポレートサイトはニュース記事・社員ページ含めると非常にたくさんのコンテンツ数を持っています。 そこに更に5種類のデザインテーマが選べる機能が加わったことにより、より多彩な顔を持つようになりました。 コンテンツとデザインの組み合わせの妙によっては、面白い画が生まれるという楽しみ方もあります。 ぜひ、気分によってデザインを切り替えながらお楽しみ下さい。