2014年10月17日金曜日

SVG2のmix-blend-modeを試してみる

SVG2の仕様確定が遠のいてしまいましたが,翻ってWEBブラウザ側では着実に新機能の実装が為されています.今回紹介するmix-blend-modeもその一つで,HTMLとの仕様の統合をはかる上で新たにSVG2で導入されるプロパティです.従って実用には程遠いのですが,非常に魅力的な機能ですからいち早く試してみることとしました.

なお,現状Editor's Draft版を参考としているため,今後仕様の修正に伴い内容が不正確になる可能性があります.
また,本ページの内容はmix-blend-modeをサポートしているブラウザで見てください.



mix-blend-modeとは


HTML5とSVG2とではtransformやfilter等の似通った機能について仕様が共通化されます.そのためSVG1.1までは存在しなかった様々なCSSプロパティがSVGにおいても利用可能となります.

mix-blend-modeプロパティは仕様「Compositing and Blending Level 1」によりCSSに新たに追加されたグラフィックの合成に関わるプロパティで,HTML/SVGの両方に適用可能です.

SVGでは通常,図形要素等を先頭から順に重ねあわせていくことでグラフィックを表しますが,mix-blend-modeを指定することで,既に描画済みの内容にどのように図形を描画(合成)するかを指定することが可能となるのです.

現状,firefoxとchrome/opera/safariで動作可能で,残念ながらinternet explorerでは内容が無視されます.またchrome系ブラウザにおいてもブラウザ設定を変更する必要があります.上手く動作しない場合は「chrome://flags」にアクセスし,フラグ「#enable-experimental-web-platform-features」を有効化し,ブラウザを再起動させてください.

とにかく試してみる


それはさておき,実際にどのようなことが出来るのか見てみましょう.まずは元となるSVGです.

これにmix-blend-modeプロパティを適用すると次のような結果が得られます.

このように円の共通部分の色がブレンドされ元の色とは異なる結果となっています.
コードは次のとおりです.
<svg height="200px" viewBox="0 0 200 200" width="200px">
 <g style="isolation:isolate">
  <circle cx="80" cy="70" fill="red" r="50"></circle>
  <circle cx="135" cy="100" fill="blue" r="50" style="mix-blend-mode: screen;"></circle>
  <circle cx="80" cy="130" fill="#0f0" r="50" style="mix-blend-mode: screen;"></circle>
 </g>
</svg>
SVG1.1時には存在しなかった新たなプロパティ「mix-blend-mode」がstyle属性に記述されていることがわかります.なおmix-blend-modeは現状SVGのプレゼンテーション属性として定義されていないため,style要素/属性として指定する必要があります

ここで注意すべき点としてはfilter要素を使っていない点です.filter要素でこのような合成を行おうとすると一般に記述が煩雑となる他,その特性上強制的にラスタライズが発生してしまうなどの様々な弊害がありました.しかしmix-blend-modeを用いるとベクタ状態が維持される上,非常にすっきりと記述できます.

ブレンドモードの種類


mix-blend-modeに指定可能な値はブレンドモード(blend mode)と呼ばれ,次のものがあります.
  • normal…通常(規定)※
  • multiply…乗算※
  • screen…スクリーン合成※
  • ovarlay…オーバーレイ合成
  • darken…比較暗※
  • lighten…比較明※
  • color-dodge…覆い焼き
  • color-burn…焼きこみ
  • hard-light…ハードライト
  • soft-light…ソフトライト
  • difference…差の絶対値
  • exclusion…除外
  • hue…色相
  • saturation…彩度
  • color…カラー
  • luminosity…輝度
この内※が付いているものはSVG1.1におけるfeBlendのmodeプロパティに対応しており, この点でCSSのブレンドモードはSVG1.1の拡張となっています.実際これらの値をfeBlend要素に指定することが可能です.

と,mix-blend-modeの説明はこれで十分なのですが,ここで目ざとい方はもうひとつ,見慣れないプロパティが存在していることに気が付かれたかと思います.図形要素を囲んでいるg要素に「isolation:isolate」というスタイルです.

isolationプロパティの作用


isolationプロパティは主にSVGのコンテナ要素に設定されるもので,子要素の背景グラフィックへの合成順序を指定します.指定できる値は次の何れかです.
  • normal…子要素は上から順に指定されたmix-blend-modeのブレンドモードを元に逐次背景に合成されていきます
    (SVG2ではこの内容でg要素の描画が再定義されています)
  • isolate…子要素達は一旦黒の透明で塗りつぶされた一時バッファにおいて順次描画(合成)され,その後背景に合成されます.なおこのisolation:isolateが指定された要素を「(カンバスから)分離されている」と呼びます.
    (SVG1.1ではかつてこちらで説明されていました)
なお仕様では暗黙的な「分離」についても言及されており,opacity属性,filter処理,transform3d(等)が適用されたコンテナ要素は暗黙的にカンバスから分離される事になっています.

従って先程の例でisolateを指定した場合とそうでない場合とでは次のような違いが発生します.

  • normal…pinkの背景色と合成が発生するため,色が溶け込んでしまう.

    <svg height="200px" width="200px">
    <rect width="100%" height="100%" fill="pink"></rect>
    <g style="isolation: normal;">
    <circle cx="80" cy="70" fill="red" r="50"></circle>
    <circle cx="135" cy="100" fill="blue" r="50" style="mix-blend-mode: screen;"></circle>
    <circle cx="80" cy="130" fill="#0f0" r="50" style="mix-blend-mode: screen;"></circle>
    </g>
    </svg>
  • isolate…g要素の内容が合成された後,pinkの背景に重ね合わされている.

    <svg height="200px" width="200px">
    <rect fill="pink" height="100%" width="100%"></rect>
    <g style="isolation: isolate;">
    <circle cx="80" cy="70" fill="red" r="50"></circle>
    <circle cx="135" cy="100" fill="blue" r="50" style="mix-blend-mode: screen;"></circle>
    <circle cx="80" cy="130" fill="#0f0" r="50" style="mix-blend-mode: screen;"></circle>
    </g>
    </svg>

なおfirefoxではこのisolateプロパティをサポートしていません.その代わりにtransform属性を追加すると何故かisolate状態となります.
  • g要素にtransform="translate(0,0)"を指定した

    <svg height="200px" width="200px">
    <rect fill="pink" height="100%" width="100%"></rect>
    <g style="isolation: isolate;" transform="translate(0,0)">
    <circle cx="80" cy="70" fill="red" r="50"></circle>
    <circle cx="135" cy="100" fill="blue" r="50" style="mix-blend-mode: screen;"></circle>
    <circle cx="80" cy="130" fill="#0f0" r="50" style="mix-blend-mode: screen;"></circle>
    </g>
    </svg>

このように,現状不安定でとても実用に耐えうるものではありませんが,将来こういうものが使えるようになる(かもしれない)ので,憶えておくと良いでしょう.

0 件のコメント:

コメントを投稿