この記事は SVG Advent Calendar 2014 の1日目の記事です。
SVG とは?
SVG Advent Calendar の初日ということで、簡単に SVG そのものの紹介をしておきましょう。
WikiPediaの記事 → http://ja.wikipedia.org/wiki/Scalable_Vector_Graphics
SVG 1.1 Second Edition の厳密な定義 → http://www.w3.org/TR/SVG/(英語)
手書きする人向けの日本語での解説 → http://www.h2.dion.ne.jp/~defghi/svgMemo/svgMemo_01.htm
なお、この記事には SVG画像 を直接記述しています。ブラウザによっては正しく表示されないことがあるかもしれません。特に古いやつとか。予めご了承下さいませ。
実演に使う画像
この記事では、以前の記事
で掲載した写真を 160px * 120px にリサイズした、
を題材にして、いろいろと実演していきたいと思います。
clip とは?
画像を切り抜くやつです。
ここで言う「画像」とは、いわゆる写真(<image>
要素)だけでなく、SVGの図形や文字なども含みます。
例えば、こんな SVG を書くと
<?xml version="1.0"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="320" height="240" viewBox="0 0 320 240"> <rect stroke="none" fill="#ffffc0" x="0" y="0" width="320" height="240"/> <image xlink:href="http://img.f.hatena.ne.jp/images/fotolife/t/t_motooka/20141130/20141130232505.jpg" x="80" y="60" width="160" height="120" clip-path="url(#clip1)"/> <clipPath id="clip1"> <path d="M80,60 v120 h30 v-120 z M120,60 v30 h30 l-10,20 l30,-20 v-30 z M120,150 v30 h50 v-30 z M240,60 h-40 l-30,60 l30,60 h40 l-30,-60 z" clip-rule="even-odd"/> </clipPath> </svg>
こんな図形が出来上がります。
<image>
要素に添えられたclip-path
属性が、<clipPath>
要素のid
属性の値を指し示しているからこそ、このclipが実現するのです。
SVG における clip の詳細は、こちら http://www.w3.org/TR/SVG/masking.html をご覧下さい。
transform とは?
画像を変形させる機能です。(ここで言う画像とは…clipのところと同じ)
2次元のアフィン変換で処理できることであれば、(その動作原理さえ知っていれば)簡単に記述することができて非常に便利です。
例えばこんな SVG を書くと
<?xml version="1.0"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="320" height="240" viewBox="0 0 320 240"> <rect stroke="none" fill="#ffffc0" x="0" y="0" width="320" height="240"/> <image xlink:href="http://img.f.hatena.ne.jp/images/fotolife/t/t_motooka/20141130/20141130232505.jpg" x="80" y="60" width="160" height="120" transform="rotate(30, 160, 120)"/> </svg>
こんなのができあがります。
<image>
要素のtransform
属性の値に着目して下さい。rotate(30, 160, 120)
は、座標(160,120)
を中心として、30°だけ時計回りに回転するという意味です。
SVG における transform の詳細は、こちら http://www.w3.org/TR/SVG/coords.html をご覧下さい。
clip した結果を transform してみる
ここでは、clip した結果、即ち「にく」の字形も、肉の画像も、どちらも 30°だけ時計回りさせてみましょう。
これは簡単です。
<?xml version="1.0"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="320" height="240" viewBox="0 0 320 240"> <rect stroke="none" fill="#ffffc0" x="0" y="0" width="320" height="240"/> <image xlink:href="http://img.f.hatena.ne.jp/images/fotolife/t/t_motooka/20141130/20141130232505.jpg" x="80" y="60" width="160" height="120" clip-path="url(#clip1)" transform="rotate(30, 160, 120)"/> <clipPath id="clip1"> <path d="M80,60 v120 h30 v-120 z M120,60 v30 h30 l-10,20 l30,-20 v-30 z M120,150 v30 h50 v-30 z M240,60 h-40 l-30,60 l30,60 h40 l-30,-60 z" clip-rule="even-odd"/> </clipPath> </svg>
この SVG を与えてあげれば
このように表示されます。
<image>
要素に付加されている属性に着目して下さい。clip-path
属性とtransform
属性の両方が指定されていますね。
transform で変形したものを clip してみる
それでは、回転させた画像を clip するには、どうしたら良いのでしょうか? そう、ここでは貴方は「にく」の字形は回転させたくないのものとします。
直感的には、上記の「clip した結果を transform してみる」と同じ書き方で良さそうですが、これだと上記のような結果になります。
これこそが、多くの SVG 手書き初心者を悩ませるポイントの一つです。
ある程度 SVG に慣れている方であればもう想像ついているかと思いますが、transform
をかけた<image>
要素の外側で clip してあげればOKです。具体的には<g>
を使います。
<?xml version="1.0"?> <!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd"> <svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" width="320" height="240" viewBox="0 0 320 240"> <rect stroke="none" fill="#ffffc0" x="0" y="0" width="320" height="240"/> <g clip-path="url(#clip1)"> <image xlink:href="http://img.f.hatena.ne.jp/images/fotolife/t/t_motooka/20141130/20141130232505.jpg" x="80" y="60" width="160" height="120" transform="rotate(30, 160, 120) translate(160, 120) scale(1.5, 1.5) translate(-160, -120)"/> <clipPath id="clip1"> <path d="M80,60 v120 h30 v-120 z M120,60 v30 h30 l-10,20 l30,-20 v-30 z M120,150 v30 h50 v-30 z M240,60 h-40 l-30,60 l30,60 h40 l-30,-60 z" clip-rule="even-odd"/> </clipPath> </g> </svg>
このようにしてあげれば
きちんと、回転した結果を clip してくれるようになります。
なお、ここでは、そのまま回転するだけだと文字の形が変わってしまうので、一緒に1.5倍の拡大をかけています。transform
属性の中で scale
(拡大縮小) を translate
(平行移動) で挟んでいるのは、SVGに限らず、二次元のアフィン変換を使うときの必須テクニックです。拡大縮小の起点を一旦座標平面の原点に戻してあげている訳です。内部的には rotate
も似たようなことをやってるはずなんですけどね。
※本来、<clipPath>
要素は<defs>
要素の中に記述するのが良いのですが、この記事ではコード量削減のため、それを実践しておりません。ゴメンなさい。。
次の日
次の2日目は、 memoca_ さんによる「filter を使ったマウスオーバー効果」の予定です。
公開され(たのを検知し)次第、リンク追記します。
☆追記 on 2014.12.02 AM8時頃☆
2日目の記事が公開されました!
[SVG] filter 要素の基本的な使い方と filter 要素をつかったモノクロからカラーへ変化するマウスオーバー効果を作る方法 | memocarilog
(追記ここまで)
関連書籍
- 作者: 相澤裕介
- 出版社/メーカー: カットシステム
- 発売日: 2014/07
- メディア: 単行本
- この商品を含むブログを見る
- 作者: J. David Eisenberg
- 出版社/メーカー: Oreilly & Associates Inc
- 発売日: 2002/02
- メディア: ペーパーバック
- クリック: 37回
- この商品を含むブログ (2件) を見る
☆追記 on 2014.12.02 AM8時頃☆
- 作者: J. David Eisenberg,Amelia Bellamy-royds
- 出版社/メーカー: Oreilly & Associates Inc
- 発売日: 2014/11/03
- メディア: ペーパーバック
- この商品を含むブログを見る
※ブコメで教えてくれた id:rikuo さん、ありがとうございました!!
(追記ここまで)