TECHNOLOGY 2014.02.05

できる!IE8のCSS3(的な)表現

  • HTML5/CSS3
  • javascript

WindowsXPを利用しているユーザーがIE8で止ってるのは周知の事実です。
このレガシーブラウザが要件に入ってくると、当然IE9以降を対象としたコンテンツと比べて出来ることが限られてきます。 これを工数にハマる範囲でいかにカジュアルに、IE8も対象になるようにフォールバック出来るかが実装の勝負どころです。

CSS3に対応していないIE8でも、独自機能を使ったらCSS3のある程度の機能はフォールバック出来そうじゃない?
ということで使ってみたのがこの独自機能です。

filter:progid:DXImageTransform.Microsoft.Matrix

名前からしてIE独自機能感ハンパない。

Flashなんかをやっていた人には馴染みがあるMatrix(変換行列)という単語がありますね。

※Matrixが聞き慣れない方は、にゃあプロジェクトのひろゆき先生の記事がわかりやすいのでどうぞ。
(Flashの記事ですが基本的な考え方は同じです)
http://www.project-nya.jp/modules/weblog/details.php?blog_id=615

要は、回転とかスケールとかがIE8でもいけるぜという話ですが、この機能はFlashのActionScriptには入っててJavaScriptにはないんです。

ないものは自分で作るかお借りする。

CreateJSというJavaScriptのライブラリの中にMatrix2Dという名前でクラスが提供されているので、こちらからお借りするのが得策かと思います。
http://www.createjs.com/#!/CreateJS

CreateJSのMatrix2Dクラスを使って作ったIE8でも回転してるサンプルコードがこちらです。

http://jsrun.it/asou_jp/8cgB
jsdo.it のサイト自体がIE8に対応していないので、代わりにjsrun.it にドメインを書き換えて閲覧できるようにしています。

// CreateJSのMatrix2Dクラスに行列の演算を任せる
matrix2d.identity();
matrix2d.rotate(obj.rotation * DEG_TO_RAD);

ここが肝心の行列演算をしてくれてる部分です。
rotateメソッドは角度ではなくラジアン角を利用しますので、Matrix2D.DEG_TO_RADを回転角度に掛けてあげると期待通りの動きをしてくれます。
再利用をする場合、identity() を叩いてあげないと、前回の状態が残っていて変な感じになりますので注意が必要です。

// IE8のMatrixに演算結果を渡す
element.style.filter = 'progid:DXImageTransform.Microsoft.Matrix(M11=' + matrix2d.a + ', M12=' + matrix2d.c + ', M21=' + matrix2d.b + ', M22=' + matrix2d.d + ', SizingMethod="auto expand");';

後は行列演算の結果をIE8のfilter:progid:DXImageTransform.Microsoft.Matrixに渡してあげるだけです。

実際にIE8で実行した際のアニメーションがこちらです。

でも思ってたヤツとなんか違って、変な感じに回転してる。
誰もこんな使い方するわけないのにどうしてこうなったんだよマジで。
なかなか面白い動きをしますね。

CSS3の場合は基準点を指定していないケースではいい感じに中央が軸になります。
今回はJavaScript側でCSS3の機能をフォールバックさせたい思惑があったので、こちらも同じような表示結果になって欲しいものです。

で、基準点を補正するように修正しました。

http://jsrun.it/asou_jp/4O77

updatePoint = function () {
    // 変数定義
    var top, left, width, height, b, d;

    // matrix
    matrix2d.identity();
    matrix2d.rotate(obj.rotation * DEG_TO_RAD);

    // 画像サイズ
    width = element.width;
    height = element.height;

    // b, d の正の整数化
    b = matrix2d.b < 0 ? -matrix2d.b : matrix2d.b;
    d = matrix2d.d < 0 ? -matrix2d.d : matrix2d.d;

    / IEの基準点の座標補正
    top = (height - width * b - height * d) * 0.5;
    left = (width - height * b - width * d) * 0.5;

    // マージンの適用 (position が absolute とかだと、top left)
    element.style.marginLeft = left + 'px';
    element.style.marginTop = top + 'px';
};

35行目以降にupdatePointという関数の処理を追加していて、この中で基準点を補正する処理を行っています。
この処理を、filter:progid:DXImageTransform.Microsoft.Matrixを適用した後に実行しています。

万事うまく行きました、めでたしめでたし。

この機能には少し問題点もあって、透過PNGとかでアルファチャンネルの輪郭に黒いフチのようなジャギーが入ります。
動きのある部分でこの機能を利用して、回転角度が0の時はfilterが自動的に外れるようにして、うまくごまかすのが好ましいと思います。

参考サイト:
http://p2b.jp/2009/12/24/CSS3-Transform-for-IE8