tech.kayac.com、ささやかにリニューアルしました!
tech.kayac.comをご覧の皆さん、はじめまして。意匠部ME課のfuchigamiといいます。
どうして技術部ブログに意匠部の野郎が?って感じですが、
技術部ブログのリニューアル記念ということで、ちゃっかりcanvasについて記事を書こうと思います。
最初なので、、、
簡単にぼくの属性を説明すると、html5とか好き、CSS3とか好き、canvasとか興味ある、非モテ、javascriptはjQueryがなんとなくわかる程度、非リア充。こんな感じです。
今回のリニューアルではコーディング全般を担当しました。
特に、プログラミングに関してはド素人だ!ということを強調しておきます。
そんなぼくが、canvasを使ってキラキラした背景を作ってみました
「リニューアルするからには新しいことがやりたいよね。だったらhtml5とcss3だろう。せっかくだからcanvas使いたい。」という自然な流れのもと、これはチャンスだ!と、前々から温めていた「canvasを背景に使う」ネタをやろうと思いました。
そうなんです、実はこのブログの背景、canvasで表示しています。
あれ、canvasってなんだっけ??
canvasはhtml5から追加された要素で、javascriptから図形などの描画ができます。
つい先日も当ブログで取り上げられましたね。雰囲気としてはprocessingに近いかな?といった感じです。
今更聞けないcanvasの基礎の基礎
ピンとこない人もいるかもしれませんが、実際に見てみると
その可能性にドキドキしちゃうはずです。
この有名なcanvasのデモ、超カッコいいですね。
HTML5 Canvas and Audio Experiment
ということで、canvasを使ってみた経験を踏まえて、この背景の作り方を書きたいと思います。
canvasを背景にします。
では実際に書きながら作っていきたいと思います。
htmlとcssを書く
まずはcanvasタグをhtmlに配置してみましょう。ウインドウサイズいっぱいにするために、divで囲っておきます。
これだけだと、canvasは 300px × 150px のただの長方形ですね。
とりあえず、#wrapperを画面全体に広げて固定配置にしましょう。
html{ min-height: 100%; overflow: auto; position:relative; z-index: 1; background: #000; } body{ min-height: 100%; margin: 0; padding: 0; overflow: auto; position: relative; z-index: 1; } body > #wrapper{ height: auto; overflow: auto; position: fixed; z-index: 1; width: 100%; height:100%; min-height:100%; } canvas{ z-index: 1; position: fixed; }
余計なスタイルが混じっているかもしれませんが、とりあえずこれで#wrapperが全画面かつ固定配置になったはずです
canvasのサイズを決めよう
canvasにはサイズの指定方法が2種類あります。
- canvasタグのwidth属性・height属性で指定
- cssで幅と高さを指定
なんとなくCSSでサイズを指定したくなります。ですが、CSSでサイズを決めると問題がありました。なんと、単純に引き延ばされるだけで、canavsの実際の大きさは変わってないみたいなんです。imgタグにサイズcssでサイズ指定するような感じです。
なので、ここはwidth属性とheight属性にサイズを指定することにします。(cssでサイズ指定できる方法があったら教えてください!)
しかし、再び問題発生。
width="100%" height="100%"としても、100px×100pxのcanvasが表示されてしまいます。
どうやら、canvasの高さと幅は%で指定しても単位が無視されてしまうみたいですね。
javascriptの力を借りてみる
どうやらhtmlとcssだけではcanvasを背景にできないぞ。そう悟ったぼくはjavascriptでサイズを指定することにしました。雰囲気JSer渕上の誕生です。
イメージ的には、div#wrapperのサイズを取得して、canvasのwidth属性・height属性に指定する、というもの。
以下のように書いてみると上手くいきました。
きっともっとスマートに書けるはずですが、深いことは考えずに行きましょう。
function sizing(){ $("#canv").attr({height:$("#wrapper").height()}); $("#canv").attr({width:$("#wrapper").width()}); }
これでcanvasをウインドウサイズにして固定配置にすることができました。
続いて、キラキラした光を描いていきます
canvasを背景のように配置することができたので、次にcanvasの内側を作っていきます。
まずは基礎の基礎を。
何事も基礎が大事です。そうです、あのエントリーをじっくりよんで勉強しましょう。
今更聞けないcanvasの基礎の基礎
nagataくん、ありがとう!
本当によく書けた記事ですね。基礎が理解できたところで、光を描画する仕組みを考えてみたいと思います。
いかにして光を表現するか
結論から言うと、以下の手順で光っぽい表現を実現しています。
- ランダムな場所に、ランダムな半径の、ランダムな色の、円を複数描く
- 円の中心から外周に向かって透明度のグラデーションをかける。→ぼかし
- 円の色をglobalCompositeOperation = "lighter";でブレンドする
→photoshopでいうところの「覆い焼き(リニア)-加算」に近い感じ
photoshopで画像を作るときと、基本的には同じ考え方ですね。
canvasで再現しよう
それではこれをcanvasで再現してみましょう。再び雰囲気JSer渕上の登場です。
円を描く準備
var star = new Array(10); //円の情報を格納する配列を作る for( i=0; i<star.length; i++ ){ star[i] = new Array(7); star[i][0] = Math.random()*canvas.width; // x座標をランダムに決める star[i][1] = Math.random()*canvas.height; // y座標をランダムに決める star[i][2] = Math.random()*canvas.width/3 + canvas.width/14; // 半径rをランダムに決める var r = Math.random()*255; // R 円の色を決める var g = Math.random()*255; // G var b = Math.random()*255; // B r = Math.ceil(r); g = Math.ceil(g); b = Math.ceil(b); star[i][4] = r; //r star[i][5] = g; //g star[i][6] = b; //b }
なんとなく配列とか使えばいいんじゃないの、というド素人感丸出しですが、要するに円の情報をランダムに決めています。
グラデーションをかけて、円を描画する
var draw = function draw(){ //reset ctx.globalCompositeOperation = "source-over"; ctx.fillStyle = "rgba(0, 0, 0, 1)"; ctx.fillRect(0, 0, canvas.width, canvas.height); ctx.globalCompositeOperation = "lighter"; //point for(i=0; i<star.length; i++){ ctx.beginPath(); var edgecolor1 = "rgba(" + star[i][4] + "," + star[i][5] + "," + star[i][6] + ",0.93)"; var edgecolor2 = "rgba(" + star[i][4] + "," + star[i][5] + "," + star[i][6] + ",0.6)"; var edgecolor3 = "rgba(" + star[i][4] + "," + star[i][5] + "," + star[i][6] + ",0.1)"; var edgecolor4 = "rgba(" + star[i][4] + "," + star[i][5] + "," + star[i][6] + ",0)"; var gradblur = ctx.createRadialGradient(star[i][0], star[i][1], 0, star[i][0], star[i][1], star[i][2]); gradblur.addColorStop(0,edgecolor1); gradblur.addColorStop(0.4,edgecolor1); gradblur.addColorStop(0.7,edgecolor2); gradblur.addColorStop(0.9,edgecolor3); gradblur.addColorStop(1,edgecolor4); ctx.fillStyle = gradblur; ctx.arc(star[i][0], star[i][1], star[i][2], 0, Math.PI*2, false); ctx.fill(); } };
なんとなくforとか使って円をいっぱい書いています。ふたたびド素人感丸出しですね。
だれかぼくにプログラミングを教えてください。
グラデーションの指定がやたらと細かくなっているのは、ちょうどいいぼかし具合をさぐった結果です。
canvasにブラーフィルターが実装されたらうれしいんですが、どうなんでしょうか。
以上のようなスクリプトを書いた結果、この背景のようなキラキラした光が表現できました。
光っぽく見せるポイント
-
色のブレンド方法を指定
globalCompositeOperation = "lighter"
この指定こそがキモです。 -
円のエッジをぼかす(ぼかしている風に見せる)
グラデーションを使って円のエッジをぼかしているように見せます。
色を rgba(100,100,100,0.5) のようにrgba指定することでアルファのグラデーションをかけることができます。
おわり
以上、ざっくりとでしたが、このブログの背景の作り方をまとめてみました。
canvasっていろんな可能性があるんだな?と思っていただければ幸いです!