2012年7月31日火曜日

サイズ不定のsvgで右辺下辺を基準とした描画を行う

svgはベクタグラフィックを記述できる言語ながら,htmlのようにサイズを固定せず任意サイズのグラフィックを定義することができます.となると例えば画像をリサイズした際に常に右下にアイコンを表示させる等の,右辺や下辺を基準としたグラフィックの描画をしたくなります.

htmlではcssのrightやbottomプロパティを用いることで簡単に実現できますから,svgでも何とかなりそうですが,いざ試してみるとこれが中々難しいことが判ります.svgではグラフィックの描画の基準点を左上にしか取ることが出きないからです.ではどうすればよいのでしょうか?

※追記 background-imageに設定するとoperaで上手くいかんね.

この問題を解決する鍵はxやy属性に設定可能な「100%」値が握っています.横位置が100%であれば図形の描画位置は左から数えて100%の位置,つまり右端となります.ですから,この100%を図形の定義に設定できれば解決するはずです.

ですが,この「100%」を指定することができる属性はx,y,width,height等の直接位置や大きさを表すものに限られます.つまり,path要素を使った場合,パスを定義するd属性にこの「100%」を指定することができないのです.さて困りました.図形の形によらず描画の基準を右端とする方法は無いのでしょうか?

ここでsvgの構造についておさらいしてみましょう.svgはグラフィックを定義する際のルートとなる要素ですが,実は入れ子にすることができます.つまりsvgの中に新たにsvg要素を定義することができるのです.これはhtml文書の中にsvgを定義するのと同じく,svgグラフィックの内部に新たなsvgグラフィックの領域を定義します.新たなグラフィック領域を定義するため,座標軸も新たに定義され,その原点はsvg要素の左上となります

勘の良い人は次にどうすればよいか分かったかもしれません.つまり,右端を基準とした描画を行うためのsvg要素を新たに定義し,その横位置を「100%」に設定するのです.そして図形はこの子svg要素内部に記述するようにします.するとこの図形は子svg要素における左端=親svg要素における右端を基準として描画されます.

しかしこれだけではまだ上手く行きません.描画しようとしている図形が子svg要素の描画範囲外に配置されてしまっているからです.この問題はsvg要素のoverflow属性をvisibleに設定することで解消することができます.

それでは実際に試してみましょう.以下は何れも同じsvgをサイズの異なるimg要素で表示したものです.何れも四隅に丸が表示されていることでしょう.

※08/01補足
サイズを固定し,preserveAspectRatioを使っても同様の効果を得ることができますが,両端に図形を描画するには使えません.まぁ,画像を重ねてしまえば済むのですが.




<?xml version="1.0" standalone="no"?>
<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1">
 <defs>
  <circle id="corner" cx="10" cy="10" r="10" fill="red"/>
 </defs>
 <svg xmlns="http://www.w3.org/2000/svg" x="0" y="0" width="20" height="20">
  <use xlink:href="#corner" x="0" y="0" width="20" height="20"/>
 </svg>
 <svg xmlns="http://www.w3.org/2000/svg" x="100%" y="0" width="20" height="20" overflow="visible">
  <g transform="translate(-20,0)">
   <use xlink:href="#corner" x="0" y="0" width="20" height="20"/>
  </g>
 </svg>
 <svg xmlns="http://www.w3.org/2000/svg" x="0" y="100%" width="20" height="20" overflow="visible">
  <g transform="translate(0,-20)">
   <use xlink:href="#corner" x="0" y="0" width="20" height="20"/>
  </g>
 </svg>
 <svg xmlns="http://www.w3.org/2000/svg" x="100%" y="100%" width="20" height="20" overflow="visible">
  <g transform="translate(-20,-20)">
   <use xlink:href="#corner" x="0" y="0" width="20" height="20"/>
  </g>
 </svg>
</svg>

0 件のコメント:

コメントを投稿