SVGの基本

SVGの基本

目次
  1. SVGについて
  2. viewBoxとwidth属性・height属性
  3. 基本的な図形
  4. 色をつける
    1. fillとstroke
    2. グラデーション
    3. パターン
  5. テキスト入力
  6. トランスフォーム属性
  7. クリッピングとマスキング
  8. imags要素

SVGについて

SVGは、ベクター形式(データを数値で管理)の画像フォーマット(パソコンで画像を取り扱うための規則)の1つです(拡張子は「.svg」)
SVGはXMLという「マークアップ言語(タグで囲んで構造を表現し、意味付けする言語)」なので、テキストエディタで描画や編集ができ、HTMLファイルに埋め込むことができます
*(注意)XMLはHTMLとは異なり大文字と小文字を区別します

SVGの特徴

  • 拡大してもギザギザがあらわれることなく画像が劣化しない
  • 解像度を気にすることなく、複数の画像を用意する必要がない
  • アニメーションが可能
  • 画像ファイルとして読み込む以外に、HTMLに埋め込んで記述できる

*写真のような画像には不向きで、平面座標系のため3Dの描画はできない

SVGファイル(.svg)を、画像ファイルとして読み込む

 <!-- img要素のsrc属性に -->
<img src="../images/hoge.svg" width="50" height="50" alt=""> 
 <!-- ファビコンに -->
<link rel="icon" href="images/favicon.svg" type="image/svg+xml">

svg要素として、HTMLに埋め込む
svg要素はHTMLのDOM ツリーとして、CSS やJavaScriptで操作できます
*svg要素はインライン要素です

 <svg xmlns="http://www.w3.org/2000/svg" width="" height="" viewBox="x y width height">
  <!-- ここにSVGの要素を記述 -->
</svg>

svg要素のおもな属性

xmlns
「xmlns=”http://www.w3.org/2000/svg”」は、URI のように見えますが「名前空間名」です
名前空間は、SVGとHTMLで同じタグや属性があるので、SVGとHTMLを区別するためのものです
(省略可)
xmlns:xlink
「xmlns:xlink=”http://www.w3.org/1999/xlink”」も「名前空間名」です
href属性(a要素やuse要素などで利用)を使うときに必要(省略可)
version
SVG のバージョンを指定(省略可)
*SVG2では非推奨
width
svg要素を表示する幅(ビューポートの幅)
*CSSで指定する場合は不要
数値のみの場合はpxとみなされます
height
svg要素を表示する高さ(ビューポートの高さ)
*CSSで指定する場合は不要
数値のみの場合はpxとみなされます
viewBox
ビューポートとは別の座標系を指定します
viewBox="x y width height"
「xとy」で左上の座標で、指定しないときは0 0を書きます
「width」は、X軸の幅
「height」は、Y軸の高さ

<svg>要素は入れ子にできます(<svg>の中に<svg>OKです)

viewBoxとwidth属性・height属性

*「viewBox」の表示がない場合(デフォルト)では「viewBox」のサイズは「ビューポート」のサイズと同じです

「ビューポート(widthとheight属性で決まります)」と「viewBox」では、異なる「単位」と「座標軸」があります
ちなみに、「viewBox」はユーザから見えている範囲、「ビューポート(widthとheight属性で決まります)」はsvg要素の表示領域です
(注意)ここでいうビューポートは「ウィンドウの見えている部分」ではありません、widthとheight属性で決まるsvg要素の表示領域のことです

デフォルトは「ビューポート」と「viewBox」は同じ大きさです

単位について
「widthとheight属性の単位」は、pxなどの絶対単位(%も可能)ですが、「viewBoxの単位」は「ビューポート」の大きさで決まる、数字のみで指定する「ユーザ単位」です

「widthとheight属性の値(px)」「viewBoxのwidthとheight」1ユーザ単位
1000と1000500と5002px=1ユーザ単位
大きく表示されます
1000と10001000と10001px=1ユーザ単位
大きさに変化なし
500と5001000と10000.5px=1ユーザ単位
小さく表示されます

widthとheightを指定せず(または100%)「viewBox」のみを指定したときは親コンテンツ幅に合わせてsvg要素は可変します

座標軸は、「ビューポート」「viewBox」ともに画面の左上を原点(0,0)です
「viewBox」は、最初の数字2つ(「viewBox=”x y width height”」)「x 」と「y」を0以外で指定すると原点が移動します(赤と青の矢印)
グレー色のボックスの幅が「viewBoxのwidth」、高さが「viewBoxのheight」です
黄色の枠は、「ビューポート」です

viewBoxのイメージ

ややこしいのは、「ビューポート」と「viewBox」でアスペクト比が異なるときです
「preserveAspectRatio」属性で、はみ出した部分をどうするかなどを指定できます
デフォルトで「preserveAspectRatio=”xMidYMid meet”」が設定されています
「meet」は、アスペクト比を保持して元画像の長いほうを領域に合わせ、「xMidYMid」は、中央でそろえるようにして「ビューポート」内に「viewBox内の要素」をおさめます

「preserveAspectRatio=”none”」を指定するとアスペクト比が崩れます

できるかぎり、アスペクト比は同じにしたいものです💦

基本的な図形

実際の図形はドローツールで描いて、エクスポートして使うのが簡単です😅
XMLの構造だけわかればOK

rect
長方形を描画
<rect x="" y="" rx="" ry="" width="" height=""/>
x:X座標(左上の位置)
y : Y座標(左上の位置)
width : 長方形の幅
height : 長方形の高さ
rx : 長方形の角の、X 軸方向の半径(角を丸くするとき)
ry : 長方形の角の、Y 軸方向の半径(角を丸くするとき)
circle
円を描画
<circle cx="" cy="" r=""/>
r : 円の半径
cx : X座標(円の中心の位置)
cy : Y座標(円の中心の位置)
ellipse
楕円を描画
<ellipse cx="" cy="" rx="" ry=""/>
rx : 楕の半径 (X軸方向)
ry : 楕の半径 (Y軸方向)
cx : X座標(楕円の中心の位置)
cy : Y座標(楕円の中心の位置)
line
直線を描画 (始点と終点を結びます)
<line x1="" x2="" y1="" y2=""/>
x1 : X座標(始点の位置)
y1 : Y座標(始点の位置)
x2 : X座標(終点の位置)
y2 : Y座標(終点の位置)
polyline
連結された直線のグループ
<polyline points="0 0, 10 20,........"/>
points : X座標とY座標の間は数値は空白、次のX座標とY座標をカンマで区切ります
polygon
多角形(終端で線が最初の点とつながり閉じます)
<polygon points="0 0, 10 20,…….."/>
points : X座標とY座標の間は数値は空白、次のX座標とY座標をカンマで区切ります
path
複雑な形状の描画が可能です
d属性は、値にコマンドをとり要素の形状を定義します
例 <path d="m 10 10 h 90 v 90 h 10 Z"/>
*コマンドの大文字はページ上の絶対座標を指定し、小文字は相対座標を指定します
m:2つの点
l:直線を描画
h : 水平線
v : 垂直線
z : パスを閉じる
cとs : 三次ベジェ曲線
qとt: 二次ベジェ曲線
a : 円弧

図形の組み合わせや簡単な曲線は、Google図形描画が簡単です
もちろんエクスポートできます(Googleアカウントが必要ですが、Figmaなどの高機能なツールを使うほどでもないときは重宝します😊 )
*必要なパスは、ほぼ最終行です

色をつける

fillとstroke

fillとstroke属性

「fillは塗りつぶしの色」 「strokeは枠線の色」を設定します
*値は「色名・16進数値・RGB値 ・RGBA 値」など、CSSと同じです

「fill-opacity属性」で「塗りつぶしの色」、 「stroke-opacity属性」で「枠線の色」の透明度を別々に指定できます

stroke="" fill="" fill-opacity="" stroke-opacity=""

ストロークを描画するときの属性

stroke-width
ストロークの幅
stroke-linecap
開いている線の端の形状
butt : パスの長さと同じ
square : パスよりも少しだけ長め
round : 先を丸める
stroke-linejoin
2本のの接続箇所
miter : とがった角(1本の角度だけを使用して四角い角を作成)
round : 丸みを帯びた角
bevel : とがった角の先を垂直に切った新しい角
stroke-dasharray
線の間隔を指定します
値が1つののときは、等間隔の破線です
値が複数のときは、カンマで区切ります
数字が2つは「最初の数字は塗りつぶされた部分の長さを」「 2 番目の数字は塗りつぶされていない部分の長さ」です
数字が3つの場合は2回ループで偶数のパターンを作り、このパターンが繰り返されます
stroke-dashoffset
線の開始位置を変更することができます

「stroke-linecap(左)」は「線の端」「stroke-linejoin(右)」は「角」をどのようにするかを指定します

stroke-linecap
stroke-linejoin

CSSの使用について

CSSのプロパティとしも使えるSVG属性がたくさんあり、例えば「fill, stroke, stroke-dasharray」もCSSのプロパティとして使えます

また、SVGの要素に style属性(style=””)を用いるて、インラインでCSSを書けます
style="stroke: black; fill: red;"

SVGの要素に:hover などの擬似クラスをあてるときは、id属性やclass属性をつけて対応します
*defs要素は、再利用するオブジェクトを定義するためのもので、要素内にオブジェクトは直接レンダリングされません(レンダリングにはuse要素をつかいます)
(注意)defs要素を使いインラインでCSSを書けますが、通常通りスタイルシートを読み込んで書くこともできます

<defs>
    <style type="text/css">
            .MyRect {
                stroke: black;
                fill: red;
            }
            .MyRect:hover {
             stroke: black;
                fill: blue;
            }
        </style>
  </defs>
  <rect x="10" height="180" y="10" width="180" class="MyRect"/>

グラデーション

グラデーションには、「線形グラデーション(linearGradient)」と「放射状グラデーション(radialGradient)」の 2 種類があります

  • グラデーションは「defs」内に定義します(再利用できます)
    id属性で名前をつけます」
  • グラデーション要素の内部には複数<stop>の要素を作成します
  • グラデーションを適用する図形はfill="url(#id名)"でグラデーションを利用します
 <svg width="120" height="240" version="1.1" xmlns="http://www.w3.org/2000/svg">
    <defs>
        <linearGradient id="Gradient" x1="1" x2="0" y1="0" y2="0">
            <stop offset="0%" stop-color="red" />
            <stop offset="50%" stop-color="black" stop-opacity="0" />
            <stop offset="100%" stop-color="blue" />
        </linearGradient>
        <radialGradient id="Gradient2" cx="0.25" cy="0.25" r="0.25">
            <stop offset="0%" stop-color="red" />
            <stop offset="100%" stop-color="blue" />
        </radialGradient>
    </defs>
    <rect x="10" y="10" width="100" height="100" fill="url(#Gradient)" />
    <rect x="10" y="120" width="100" height="100" fill="url(#Gradient2)" />
</svg>
<linearGradient>要素
線形グラデーション
デフォルトは水平方向のグラデーションです
グラデーションの方向を変更するには、「 x1・ x2・ y1・ y2 」属性で指定された2つの点を使います
<linearGradient x1="0" x2="0" y1="0" y2="1">
<radialGradient>要素
放射状グラデーション
デフォルトは図形の中心から放射線状のグラデーションです
グラデーションの中心点や大きさは「cx と cy属性で中心点」「r属性で半径」を変更できます
<adialGradient cx="0.5" cy="0.25" r="0.25">
「spreadMethod属性」で 塗りつぶされていない場合にどうするかを指定できます
spreadMethod=”pad” : 100%のカラーが残りの部分を埋める
spreadMethod=”repeat” : 100%のカラーから0%方向にグラデーションを折りかえす
spreadMethod=”reflect” : 再度0%からグラデーションが始まる
<stop>要素
グラデーションで使用する色と位置を定義します
<stop offset="" stop-color="" stop-opacity=""/>
offset:位置(「0%から100%」または「0から1」)
stop-color : 色
stop-opacity : 不透明度

パターン

パターンを設定した要素の中で、同じ画像を繰り返し描画します(背景画像になります)

  • パターンも「defs」内に定義します(再利用できます)
    「 id属性で名前をつけます」
  • pattern要素に「width 」「 height 」属性で「グラフィック要素のサイズを定義し、開始点をずらしたい場合は「 x 」「 y 」属性を指定します
  • パターンを適用する図形はfill="url(#id名)"でパターンを指定します
<svg width="1000" height="1000" xmlns="http://www.w3.org/2000/svg" version="1.1">
    <defs>
        <radialGradient id="Gradient">
            <stop offset="0%" stop-color="blue" />
            <stop offset="100" stop-color="white" />
        </radialGradient>
 <!--パターン1-->
    <pattern id="Pattern" x="0" y="0" width=".25" height=".25">
        <circle cx="25" cy="25" r="20" fill="url(#Gradient)" />
    </pattern>
 <!--パターン2-->
    <pattern id="Pattern2" x="0" y="0" width="50" height="50" patternUnits="userSpaceOnUse">
        <circle cx="25" cy="25" r="20" fill="url(#Gradient)" />
    </pattern>
 <!--パターン3-->
    <pattern id="Pattern3" width=".25" height=".25" patternContentUnits="objectBoundingBox">
        <circle cx=".125" cy=".125" r=".1" fill="url(#Gradient)"/>
    </pattern>
    </defs>

    <rect fill="url(#Pattern)" stroke="black" x="0" y="0" width="200" height="400" />
    <rect fill="url(#Pattern2)" stroke="black" x="200" y="0" width="200" height="400" />
    <rect fill="url(#Pattern3)" stroke="black" x="400" y="0" width="200" height="400" />
</svg>
SVGのパターン比較

「height」と「width」の値についての注意点

上の例の「パターン1」は、「height」と「width」を「0.25 」に指定しています
patternUnits属性」はpatternの単位を指定する属性です
「patternUnits属性のデフォルトの値」は「patternUnits=”objectBoundingBox“」で「枠となるオブジェクト全体を1」として計算します(0.25なので、4回繰り返します)
しかし、オブジェクトのサイズが変わっても繰り返す回数は同じで、「pattern要素内の基本図形(ここではcircle)」のサイズは変わりません

パターン2」は、patternの単位をデフォルトの値から「patternUnits=“userSpaceOnUse“」に変更し「width=”50” height=”50″」とピクセルで指定しています
サイズが決まっており、枠の形状に関係なく繰り返します

パターン3」は、patternの属性には「patternContentUnits属性」もあり、この属性はpattern自身の単位ではなく、「pattern要素内の基本図形(ここではcircle)」の単位を決める属性です
「patternContentUnitsのデフォルト値」は「patternContentUnits=”userSpaceOnUse”」です(patternUnits属性とは逆w)
そこで、デフォルト値から「patternContentUnits=”objectBoundingBox”」に変更し「pattern要素内の基本図形(ここではcircle)」の単位を変更しました(1をもとにして計算)
「pattern要素内の基本図形(ここではcircle)」隙間をうめるために、縦長になりました

テキスト入力

text要素
SVG内にテキストを入れることができます
「xとy属性」でテキストの位置を指定します
「fillやstroke属性」の指定もできます
<text x="10" y="10">テキスト</text>
text-anchor="middle"で文字列の中央をxとyで指定された位置にあわせることができます
alignment-baseline="middle"で文字列の中心を親要素のベースラインに親の高さの半分を加えたものに揃えることができます

その他のおもな属性(CSSでも設定できます)
font-family・font-style・font-weight ・font-variant ・font-stretch ・font-size ・font-size-adjust ・kerning ・letter-spacing ・word-spacing ・text-decoration
tspan要素
text要素またはtspan要素の子要素にしかなれません
一部の文字列のスタイルを変えたいときなどに使います
<tspan>テキスト</tspan>
xとy: 絶対X座標と絶対Y座標を設定
dxとdy : 現在位置から移動させるオフセットの値
rotate : 文字が指定した値の分だけ回転
tref要素
すでに定義しているテキストを参照(コピー)
<tref xlink:href="#example"/>
textPath
パスに沿って文字を並べます
<path id="my_path" d=..../>
<text>
<textPath xlink:href="#my_path">テキスト</textPath>
</text>

トランスフォーム属性

g要素について

「g要素」は、グループ化するために用いられるコンテナです
「g要素」の「トランスフォーム」はすべての子要素に実行さます
「g要素」の「属性」はすべての子要素に継承されます
「g要素」でグループ化しておくと、後に「use要素」で参照できます

transformの値

translate(x,[y])
移動(X軸・Y軸に指定した距離を移動します)
yを省略したときはY軸は0です
scale(x [,y])
拡大縮小(比率で拡大・縮小します)
「1」が等倍です
yを省略したときはxと同じ値です(同じ比率)
rotate(角度 [,x, y])
回転(指定された角度を時計回り回転します)
[,x, y]は、回転の中心になる座標です
[,x, y]を省略したときは要素の左上「0 0」が中心になります
skskewX(角度)
横方向にひっぱった傾斜(X軸に対する傾斜角度)
角度
skewY()
上方向にひっぱった傾斜(Y軸に対する傾斜角度)
matrix(A1, A2, B1, B2, C1, C2)
3×3の複雑なトランスフォーム

トランスフォーム属性はスペース区切りで連結できます

<g fill="red" transform="translate(30,40) rotate(45) scale(2) skewX(30)">
    <rect x="0" y="0" width="10" height="10" />
    <rect x="20" y="0" width="10" height="10" />
</g>

クリッピングとマスキング

「クリッピング」は、切り抜きです、オブジェクトの一部をまったく表示しません(白か黒です)
「マスキング」は、「半透明にしたり」「マスクをかけたり」ができます

クリッピングします
「切り抜きたい画像」は、描画している状態です

  • <clipPath>要素で、表示したい領域を設定します(領域の外側は描画されません)
  • <clipPath>要素に「id属性で名前をつけます」
  • 「切り抜きたい画像」の要素に「clip-path属性」で「clip-path="url(#id名)"」を指定します
<clipPath id="heart">
    <path d="M10,30 A20,20,0,0,1,50,30 A20,20,0,0,1,90,30 Q90,60,50,90 Q10,60,10,30 Z" />
</clipPath>

<rect x="0" y="0" width="200" height="100" clip-path="url(#heart)"/>

要素をじょじょフェードアウトしていくような演出は、「グラデーション」と要素を使ってマスキングします
「フェードアウトしたい画像」は、描画している状態です

  • グラデーションを「基本的にはdefs」内に作り、「 id属性で名前をつけます」
  • グラデーション要素の内部には<stop>要素を作成します
  • <mask>要素で、マスクをかけたい領域を設定し「fill="url(#グラデーションのid名)“」でグラデーションを指定します
  • <mask>要素に、「 id属性で名前をつけます」
  • 「フェードアウトしたい画像」の要素に「mask属性」で「mask="url(#maskのid名)"」を指定します
<defs>
<linearGradient id="Gradient">
   <stop offset="0" stop-color="white" stop-opacity="0" />
   <stop offset="1" stop-color="white" stop-opacity="1" />
</linearGradient>
<mask id="Mask">
  <rect x="0" y="0" width="200" height="200" fill="url(#Gradient)" />
</mask>
</defs>

<rect x="0" y="0" width="200" height="200" fill="red" mask="url(#Mask)" />

imags要素

要素で、画像を表示します
height属性またはwidth属性が「ないか0」のときは画像は表示されません
x属性とy属性がないときは、それらの値は「0」 になります

<svg width="500" height="500" version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink"> 
<image href="hoge.png" x="0" y="0" height="500" width="500" />
</svg>

参考