CSS2KB をちょっと改良 + CSSファイル に Canvas の描画ルーチンを埋め込む
CSSにデータを埋め込む方法を考えてみた(CSS2KB) - latest log の続き
CSS2KB とは CSS にちょっとした情報を埋め込むトリックの1つ。 list-style: url(1dot.gif?key=val) から key=val を取り出せるというもの。
CSS2KB の難点は、ダミーファイル(1dot.gif) が実際に必要だった点
- ダミーファイルのロード ⇒ 通信が余計に発生するよね
- ダミーファイルが 404 だと? ⇒ key=val が取り出せない ⇒ それってまずいよね
ダミーファイルが邪魔なので、もうちょっと考えてみた
試しに、URL を list-style: url(?key=val) だけにしてみたら
- ダミーファイル(1dot.gif)が不要に
- CSS のファイルパスが補完された形で取得できる ⇒ 補完された CSS のURLがついでに取れてくる
- この URL は何か使い道がありそうな、そんな雰囲気。
ということに(いまさら)気づいた。
サンプル
.hoge { list-style: url(?key=val) }
から key=val を取り出すには、こういったコードを用意して…
// uu.hash.css2kb - hash from CSS implemented data var _ie = !!document.uniqueID; var doc = document; function uuhashcss2kb(name) { // @param String/Array: className or [className, ...] // @return Hash: { key: val, ... } function _qsparse(m, key, value, s) { s = decodeURIComponent(value); return rv[decodeURIComponent(key)] = isNaN(s) ? s : parseFloat(s); } function _trimurl(str) { return (!str.indexOf("url(") && str.indexOf(")") === str.length - 1) ? str.slice(4, -1).replace(/^\s*["']?|["']?\s*$/g, "") : str; } var rv = {}, cs, url, v, i = 0, ary = (typeof name === "string") ? [name] : name, div = doc.body.appendChild(doc.createElement("div")); while ( (v = ary[i++]) ) { div.className = v; cs = _ie ? div.currentStyle : window.getComputedStyle(div, null); url = _trimurl(cs.listStyleImage); if (url && url.indexOf("?") > 0) { url.slice(url.indexOf("?") + 1).replace(/(?:([^\=]+)\=([^\;]+);?)/g, _qsparse); } } doc.body.removeChild(div); return rv; }
こうすれば CSS に埋め込んだ Hash を取得できる。
uu.hash.css2kb("hoge") -> { key: val }
doc.body.appendChild(div) して doc.body.removeChild(div) してるのは、IE でノードツリーに参加していない要素の currentStyle が null になるから。IE 以外なら appendChilde とかは不要。
IE6+, Safari3x+, Google Chrome, Opera9.5+ で動く
その気になれば、
CSSファイルに 文書構造(HTML)を埋め込むことも、生の画像データを埋め込むことも、はたまた js そのものを埋め込むことも自由さ。
お勧めは、HTML5::Canvas の描画ルーチンをCSSに埋め込むこと
ctx.beginPath(); ctx.fillRect(0,0,100,100); ctx.closePath();
を encodeURIComponent 等で処理して、CSS に埋め込み
.CloseButton_css2kb { list-style: url(?js=ctx.beginPath%28%29%3Bctx.fillRect%280%2C0%2C100%2C100%29%3Bctx.closePath%28%29%3B) }
これで描画できる。
function drawCloseButton(ctx) { var js = uu.hash.css2kb("CloseButton_css2kb").js; eval(js); }
ちょっとしたパラダイムシフトだ。