[CSS] SVGの使い方

SVGとは
– XMLをベースにした二次元ベクターデータ

SVGのメリット
– 拡大・縮小に強い
– 軽い
– CSSで装飾させたりアニメーションも可

デメリット
– 写真やイラスト等に向かない

### SVG作成
まずPhotoshopでSVG画像を作ります

あれ、保存できない。。
というか、SVGはillustratorで作るらしい。 なるほど。。。。

気を取り直して、illustratorで画像を作ります。

保存した状態

sublimeに当ててみると。。。

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 23.0.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="レイヤー_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px"
	 y="0px" viewBox="0 0 500 500" style="enable-background:new 0 0 500 500;" xml:space="preserve">
<style type="text/css">
	.st0{fill:none;}
	.st1{font-family:'KozGoPr6N-Regular-83pv-RKSJ-H';}
	.st2{font-size:261px;}
</style>
<rect x="14" y="106.68" class="st0" width="478" height="269.86"/>
<text transform="matrix(1 0 0 1 14 336.3662)" class="st1 st2">SVG</text>
</svg>

ほう、こんなんなってるのか。

	<h1>SVG</h1>
	<img src="/img/sample.svg">

### css表示

<div class="test"></div>
.test {
	background-image: url("img/sample.svg");
}

– fill, fill-opacity, stroke, stroke-width, stroke-dasharray, stroke-dashoffsetなど使用可能

### objectで表示

<object type="image/svg+xml" data="/img/sample.svg" width="200" height="100"></object>

### fillの例

	<svg id="test" xmlns="http://www.w3.org/2000/svg">
		<circle class="icon" cx="50" cy="50" r="50"/>
	</svg>
#test {
	fill: red;
}

画像バリデーションにおけるbmp、SVG、webpの扱い

### 画像バリデーションの拡張子
一昔前は、画像の拡張子といえば、jpeg,jpg,gif,pngのみが多かった印象がありますが(自分だけ?)、Laravel6.xのimageのバリデーションでは「jpg、png、bmp、gif、svg、webp」となっております。そのまま、jpeg,jpg,gif,pngに加えて、bmp,svg, webpも採用するかについて考えたいと思います。

### SVGとは?
SVGとは、Scalable Vector Graphicsの略です。
名称からどのような画像かほぼ想像がつきますが、念の為コードを書きながら特徴を見てみましょう。

<svg width="160" height="160">
		<rect x="0" y="0" width="160" height="160" fill="skyblue"/>
		<rect x="40" y="40" width="80" height="80" fill="tomato"/>
	</svg>

### view box

<svg width="160" height="160">
		<rect x="0" y="0" width="160" height="160" fill="skyblue"/>
		<rect x="40" y="40" width="80" height="80" fill="tomato"/>
	</svg>
	<svg width="160" height="160" viewBox="0 0 320 320">
		<rect x="0" y="0" width="160" height="160" fill="skyblue"/>
		<rect x="40" y="40" width="80" height="80" fill="tomato"/>
	</svg>

<svg width="160" height="160">
		<rect x="0" y="0" width="160" height="160" fill="skyblue"/>
		<rect x="20" y="20" width="30" height="30" fill="#08c"/>
		<rect x="65" y="20" width="30" height="30" fill="rgb(255, 0, 0, 4)"/>
		<rect x="110" y="20" width="30" height="30" fill="hsla(120, 40%, 40%, .4)"/>
	</svg>

<svg width="160" height="160">
		<rect x="0" y="0" width="160" height="160" fill="skyblue"/>
		<rect x="20" y="20" width="30" height="30" fill="#08c"/>
		<rect x="65" y="20" width="30" height="30" fill="rgb(255, 0, 0, 4)"/>
		<rect x="110" y="20" width="30" height="30" fill="hsla(120, 40%, 40%, .4)"/>
		<rect x="20" y="65" width="30" height="30" fill="none" stroke="olive" stroke-width="2"/>
		<rect x="65" y="65" width="30" height="30" fill="none" stroke="olive" stroke-dasharray="10"/>
		<rect x="110" y="65" width="30" height="30" fill="none" stroke="olive" stroke-width="2" stroke-dasharray="10, 2"/>
	</svg>

<svg width="160" height="160">
		<rect x="0" y="0" width="160" height="160" fill="skyblue"/>
		<rect x="20" y="20" width="30" height="30" style="fill:#08c; stroke:#eee; stroke-width:3;"/>
	</svg>

<svg width="160" height="160">
		<defs>
			<style>
				.my-box {
					fill: pink;
				}
			</style>
		</defs>
		<rect x="0" y="0" width="160" height="160" fill="skyblue"/>
		<rect x="20" y="20" width="30" height="30" style="fill:#08c; stroke:#eee; stroke-width:3;"/>
		<rect x="60" y="20" width="30" height="30" class="my-box"/>
	</svg>

<svg width="160" height="160">
		<rect x="0" y="0" width="160" height="160" fill="skyblue"/>
		<circle cx="80" cy="80" r="40" fill="gold" />
	</svg>	

### Photoshop、IllustratorのSVG、bmpの扱い
photoshopではbmpはありますが、SVGはありません。

一方、ベクターなのでIllustratorはSVGの取り扱いがあります。

### 結論
卒業写真など、オフィシャルなものであれば写真オンリーでしょうが、compassなどを見るとjpegの写真は殆どの見ないくらい写真以外をプロフィール画像にすることは浸透しているため、bmp,svg, webpもバリデーションに加えて良いでしょう。

プログラミングの義務教育が始まるので、近い未来、卒業写真にベクター画像を載せる学校が出てくるかもしれませんね。

svg set.attribute

<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8">
    <title>SVG</title>
  </head>
  <body>
    <svg width="600" height="300" onload="
      var c = document.getElementsByTagName('circle');
      for (var i=0; i<c.length; i++){
          c&#91;i&#93;.setAttribute('cx', r(600));
          c&#91;i&#93;.setAttribute('cy', r(400));
          c&#91;i&#93;.setAttribute('r', r(100));
          c&#91;i&#93;.setAttribute('fill', 'rgb('+r(255)+','+r(255)+','+r(255)+')');
      }
        function r(n){
          return Math.floor(Math.random() * (n + 1));
        }

    ">
      <rect width="300" height="300" fill="red" />
      <circle cx="100" cy="100" r="20" fill="white" />
      <circle cx="100" cy="100" r="20" fill="white"/>
      <circle cx="100" cy="100" r="20" fill="white"/>
      <circle cx="100" cy="100" r="20" fill="white"/>
      <circle cx="100" cy="100" r="20" fill="white"/>
      <circle cx="100" cy="100" r="20" fill="white"/>
      <circle cx="100" cy="100" r="20" fill="white"/>
      <circle cx="100" cy="100" r="20" fill="white"/>
      <circle cx="100" cy="100" r="20" fill="white"/>
      <circle cx="100" cy="100" r="20" fill="white"/>
      <circle cx="100" cy="100" r="20" fill="white"/>
      <circle cx="100" cy="100" r="20" fill="white"/>
      <circle cx="100" cy="100" r="20" fill="white"/>

    </svg>
  </body>
</html>

svgで遊ぼう


%e7%84%a1%e9%a1%8c

<svg width="600" height="300">
      <rect width="300" height="300" fill="red" />
      <text x="100" y="100" font-size="32" fill="white" stroke="black" stroke-width="2" rotate="20">
          Google
      <text>
    </svg>

transform

<svg width="600" height="300">
      <rect width="300" height="300" fill="red" />
      <rect width="100" height="100" fill="green" transform="translate(50,50)" />
      <rect width="100" height="100" fill="green" transform="skewX(30)" />
      <rect width="100" height="100" fill="white" opacity="0.2" />
    </svg>

アニメーション

<svg width="600" height="300">
      <rect width="300" height="300" fill="red" />
      <circle cx="100" cy="100" r="20" fill="white">
          <animate attributeName="r" from="20" to="80" dur="2s" repeatCount="indefinite">
      </circle>
      <circle cx="200" cy="200" r="20" fill="blue">
          <animate attributeName="r" from="40" to="120" dur="2s" begin="1s" repeatCount="indefinite">
      </circle>
    </svg>

SVG

%e7%84%a1%e9%a1%8c

    <svg width="600" height="300">
      <rect width="100%" height="100%" fill="red"/>
    </svg>

SVGでは後ろに書いたものが前に表示されます。

    <svg width="600" height="300">
      <rect width="100%" height="100%" fill="red"/>
      <rect width="100" height="50" fill="blue"/>
    </svg>

viewBox:デバイスに合わせて反映

    <svg width="600" height="300" viewBox="0 0 400 200">
      <rect width="400" height="200" fill="red"/>
      <rect width="100" height="50" fill="blue"/>
    </svg>

色の設定

    <svg width="600" height="300">
      <rect width="600" height="300" fill="red"/>
      <rect width="500" height="250" fill="#00ff00"/>
      <rect width="400" height="200" fill="rgb(0, 0, 255)"/>
      <rect width="300" height="150" fill="rgba(255,255,255,0.4)"/>
    </svg>

枠線

    <svg width="600" height="300">
      <rect width="600" height="300" fill="red" stroke="black" stroke-width="10"/>
    </svg>

sytle属性による記述

    <svg width="600" height="300">
      <rect width="600" height="300" style="fill:red; stroke:black; stroke-dasharray:20,5"/>
    </svg>

cssのような書き方

    <svg width="600" height="300">
        <style type="text/css"><!&#91;CDATA&#91;
    #myBox{
      fill:red;
      stroke:black;
    }
        &#93;&#93;></style>
      <rect width="600" height="300" id="myBox">
    </svg>

gタグ

    <svg width="600" height="300">
    <g stroke="black">
      <rect width="600" height="300" fill="red" />
      <rect width="500" height="200" fill="green" />
      <rect width="400" height="100" fill="white"/>
    </g>
    </svg>

グラデーション

    <svg width="600" height="300">
    <defs>
        <linearGradient id="g1" x1="0" y1="0" x2="1" y2="1"> 
            <stop offset="0" stop-color="skyblue" />
            <stop offset="0.5" stop-color="pink" />
            <stop offset="1" stop-color="yellow" stop-opacity="0.5"/>
        </linearGradient>
    </defs>
      <rect width="600" height="300" fill="url(#g1)" />
    </svg>

円形グラデーション

    <svg width="600" height="300">
    <defs>
        <radialGradient id="g1" cx="0.5" cy="0.5" r="0.5"> 
            <stop offset="0" stop-color="skyblue" />
            <stop offset="0.5" stop-color="pink" />
            <stop offset="1" stop-color="yellow" stop-opacity="0.5"/>
        </linearGradient>
    </defs>
      <rect width="600" height="300" fill="url(#g1)" />
    </svg>

stroke

<line x="100" y1="100" x2="200" y2="200" stroke-width="20" stroke="black" stroke-linecap="raound"  />

circle, ellipse

<circle cx="200" cy="100" r="40" fill="white" />
      <ellipse cx="400" cy="100" rx="40" ry="80" fill="green" />

polygon, polyline, path

      <polyline points="100 50 150 100 50 100" stroke="black" fill="none"/>
      <polygon points="100 50 150 100 50 100" stroke="black" fill="none"/>
      <path d="M100 50 l50 50 h100 v100 h100" stroke="black" fill="none"/>