読者です 読者をやめる 読者になる 読者になる

発芽米ぱんだのTechblog

フロントエンドエンジニアを目指す発芽米ぱんだのTechblog

【IE10・11対応】svgを使って画像をグレースケール化する

こんばんは、発芽米ぱんだです。

 

最近svgがマイトレンドです。

IEInternet Explorer)でもsvgが対応したこともあって、また高解像度のディスプレイが増えてきたこともあって、Webページにsvgが使われることは増えてきている気がします。

単純に案件で使うことが多いのもありますが、個人的にWeb上でのアニメーションに興味があるので、何かと習得したい欲が高い分野であります。

 

そもそも、svgとは何でしょうか。以下Wikipedia

Scalable Vector Graphics(スケーラブル・ベクター・グラフィックス、SVG)は、XMLベースの、2次元ベクターイメージ用の画像形式の1つである。アニメーションやユーザインタラクションもサポートしている。SVGの仕様はW3Cによって開発され、オープン標準として勧告されている。

簡単に言えば、HTMLのように書ける、全然ボケない画像っていうことです(雑

詳しくはググってください!

 

さて表題の件ですが、svgは色々と汎用性が高く、カラー画像の上にsvgのフィルタを載せるだけで、カラー画像をモノクロ(グレースケール)化することもできたりします。

 

今回は、そのグレースケール化の方法に関して書こうと思います。カラー画像とモノクロ画像を出し分けしたい時などに、使えると思います。

 

ーーー

 

さっきからsvgの話をしておりますが、

最近のCSSは優秀で、CSSだけでも画像をグレースケール化することは可能です。

 

例えば、以下。

 

発芽米ぱんだのイラスト

 

メイドラゴン終わっちゃったなぁ・・・ってのは脱線するのでよしますが、

この画像に以下のようなCSSを適用すると、

img{
    -webkit-filter: grayscale(100%);
    -moz-filter: grayscale(100%);
    -o-filter: grayscale(100%);
    -ms-filter: grayscale(100%);
    filter: grayscale(100%);
}

発芽米ぱんだのイラスト

グレースケール化します。

ただ、IEでご覧になっている方は、グレースケール化していないはずです。

 

IE対策で、少し前までは以下のようにfilterプロパティを記述するだけで解決していました。

img{
    filter: progid:DXImageTransform.Microsoft.BasicImage(GrayScale=1)
}

しかし、悲しきかな・・・DXフィルターはIE10から対応しなくなってしまいました。(参考URL:DX フィルターがサポートされなくなった (Windows)

IE10からCSS3によるfilterを標準準拠するようにしたので、IE9まで使えていたDXフィルターをなくしたようです。

「お、じゃあCSSだけでグレースケールできるね!」・・・しかしそうはさせてくれないのがIEさんです。

 

先ほどの参考URLのページによれば、DXフィルターを廃止した代わりにCSSで実装できるのは、

・Alpha(透明度)

・AlphaImageLoader(透過のpng

・Gradient(グラデーション)

・DropShadow(ドロップシャドウ)

・Matrix(3D変形)

だそうです。

IEのfilterプロパティについてはこちら(filter-スタイルシートリファレンス)をご参照ください。

 

ここまで来ると、IEでもグレースケールを表現する為には、JavaScript、もしくはsvgを使うしかなくなってきます。(え、Photoshop?どうぞご自由に・・・)

JavaScriptを使うのも勿論アリなのですが、例えば一枚の画像をグレースケール化する為だけにJavaScriptを使うなんてことは・・・解せぬ。非常に解せぬ。(個人的な心象なので、JavaScriptで解決したい方は別のページへどうぞ)

 

さて、ようやく出番が来ましたsvg

最初に答え(あくまで一例)を書いてしまいますが、以下のように記述すると、IEでもちゃんとグレースケール化してくれます。HTML内に直接記述する、インラインsvgを使います。

【HTML】

<svg xmlns="http://www.w3.org/2000/svg" class="grayscale_svg" width="100%" height="400" version="1.1">
  <defs>
    <filter id="grayscale">
      <fecolormatrix type="matrix" values="0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0.3333 0.3333 0.3333 0 0 0 0 0 1 0"></fecolormatrix>
    </filter>
  </defs>
  <image x="0" y="0" width="300" xmlns:xlink="http://www.w3.org/1999/xlink" xlink:href="https://cdn-ak.f.st-hatena.com/images/fotolife/h/htgmi/20170418/20170418002633.jpg">
</svg>

CSS

image {
  filter: url(#grayscale);
}

CSSの「url(#grayscale)」でHTMLのsvgタグ内の「id="grayscale"」箇所を呼び出しています。

hover時にグレースケールを解除したい場合などは、hover時にfilterプロパティを無効化すれば大丈夫です。

まるっとコピーして使いたい方は以下からどうぞ。

codepen.io

ただ、画像自体もsvgタグの中に記述せねばならず、svg独特の記述に則る必要がある(imgタグではなくimageタグにするなど)ので、少々使い勝手が悪いです。他にもっと良い方法があれば、追記したいと思います。

注意点として、svgタグでwidthとheightの指定を忘れずに!あと、imageのx, yの座標を指定しないといけないのも意外と盲点ですかね。このあたりもsvg特有ですね。

 

CSSのfilterプロパティで、CSSファイルと同ディレクトリに置いたグレースケールのsvgを呼び出したりもしてみたのですが、結局はIE10〜ではインラインsvgでしかうまく行きませんでした。出来たよ、って方がいらっしゃったら是非教えてください。。

 

もっとsvgとは仲良くなりたいですね!

それでは、また!