「10分でわかるSVG 応用編」サンプル

図形のグループ化

グループ化と属性値の一括指定

<g fill="#c44" stroke="#822" stroke-width="2">
  <circle cx="32" cy="32" r="30" />
  <rect x="40" y="30" width="80" height="50" />
</g>

図形の複製

<g id="s02">
  <circle cx="32" cy="32" r="30" fill="#c44" />
  <rect x="40" y="30" width="80" height="50"
        rx="10" ry="10" fill="#44c" />
</g>

<use x="140" y="0" xlink:href="#s02"
     stroke="#ccc" stroke-width="2" />

シンボルの定義と使用

<symbol id="s03" viewBox="0 0 120 80">
  <circle cx="32" cy="32" r="30" fill="#c44" />
  <rect x="40" y="30" width="80" height="50"
        rx="10" ry="10" fill="#44c" />
</symbol>

<use xlink:href="#s03"
     x="0" y="0" width="120" height="80" />
<use xlink:href="#s03"
     x="140" y="15" width="80" height="53" />

defsグループ

パス上にテキストを描画
<defs>
  <path id="s04"
        d="M 20,60 C 80,-20 180,100 240,20"
        stroke="black" fill="none" />
</defs>

<text font-size="20" dx="10" dy="-5">
  <textPath xlink:href="#s04">
    パス上にテキストを描画
  </textPath>
</text>

リンク

リンクの設置

Click Me!
<a xlink:href="http://www.atmarkit.co.jp/"
   target="_blank">
  <rect x="1" y="1" width="98" height="30"
        rx="4" ry="4" stroke="#c44" fill="#fee" />
</a>

<text x="10" y="21" pointer-events="none">
  Click Me!
</text>

URLフラグメントによる表示範囲の変更

<a xlink:href="#r">
  <circle cx="50" cy="50" r="50" fill="#c44" />
</a>
<a xlink:href="#c">
  <rect x="100" y="0" width="100" height="100"
        cx="10" cy="10" fill="#44c" />
</a>

<view id="c" viewBox="0 0 100 100" />
<view id="r" viewBox="100 0 100 100" />

図形の変形

座標変換の適用

<ellipse cx="0" cy="0" rx="50" ry="30" fill="#c44"
  transform="translate(50,40) rotate(-20)" />
<rect x="0" y="0" width="100" height="60"
  rx="10" ry="10" fill="#44c"
  transform="translate(50,40) skewX(20)" />

グループに対する座標変換

<g transform="scale(1.5,1) rotate(-20,70,40)">
  <ellipse cx="0" cy="0" rx="50" ry="30" fill="#c44"
    transform="translate(50,40) rotate(-20)" />
  <rect x="0" y="0" width="100" height="60"
    rx="10" ry="10" fill="#44c"
    transform="translate(50,40) skewX(20)" />
</g>

さまざまなSVGアニメーション

シンプルなアニメーション

<circle
  id="s09" cx="10" cy="10" r="10" fill="#c44" />
<animate
   xlink:href="#s09"
   attributeType="XML" attributeName="cx"
   dur="3s" from="10" to="290"
   repeatCount="indefinite" />

<circle cx="10" cy="30" r="10" fill="#44c">
  <animate
     attributeType="XML" attributeName="cx"
     dur="5s" from="10" by="280"
     repeatCount="indefinite" />
</circle>

キーフレームアニメーション

<circle cx="10" cy="10" r="10" fill="#c44">
  <animate
     attributeType="XML" attributeName="cx"
     dur="6s" values="10; 290; 10"
     repeatCount="indefinite" />
</circle>

色のアニメーション

<circle cx="40" cy="40" r="40">
  <animate
     attributeType="XML" attributeName="fill"
     dur="6s" repeatCount="indefinite"
     values="#c44; blue; #c44" />
</circle>

形状のアニメーション

<path fill="#c44">
  <animate
     attributeType="XML" attributeName="d"
     dur="6s" repeatCount="indefinite"
     values="M 0,0 L 40,0 80,0 40,80;
             M 0,80 L 40,0 80,80 40,80;
             M 0,0 L 40,0 80,0 40,80" />
</path>

平行移動のアニメーション

<circle cx="0" cy="0" r="10" fill="#c44">
  <animateTransform
     attributeName="transform" attributeType="XML"
     type="translate"
     dur="6s" repeatCount="indefinite"
     values="10,10; 280,10; 10,10" />
</circle>

拡大・縮小のアニメーション

<g transform="translate(50,50)">
  <circle cx="0" cy="0" r="25" fill="#c44">
    <animateTransform
       attributeName="transform"
       attributeType="XML"
       type="scale" dur="6s"
       repeatCount="indefinite"
       values="1 2; 2 1; 1 2" />
  </circle>
</g>

回転のアニメーション

<rect x="15" y="15" width="70" height="70"
      rx="10" ry="10" fill="#c44">
  <animateTransform
     attributeName="transform" attributeType="XML"
     type="rotate" from="0 50,50" to="360 50,50"
     dur="6s" repeatCount="indefinite" />
</rect>

せん断変形のアニメーション

<g transform="translate(100,30)">
  <rect x="-30" y="-30" width="60" height="60"
        rx="10" ry="10" fill="#c44">
    <animateTransform
       attributeName="transform"
       attributeType="XML"
       type="skewX" dur="6s"
       repeatCount="indefinite"
       values="45; -45; 45" />
  </rect>
</g>

パスに沿ったアニメーション(1)

<path d="M 10,40
         c 0,-80 280,80 280,0 s -280,80 -280,0"
      id="s17" fill="none" stroke="black" />

<circle cx="0" cy="0" r="10" fill="#c44">
  <animateMotion
     dur="6s" repeatCount="indefinite">
    <mpath xlink:href="#s17" />
  </animateMotion>
</circle>

パスに沿ったアニメーション(2)

<circle cx="0" cy="0" r="10" fill="#c44">
  <animateMotion
     dur="6s" repeatCount="indefinite"
     path="M 10,40 c 0,-80 280,80 280,0
           s -280,80 -280,0" />
</circle>

rotate属性の効果

<path d="M -10,-10 L 10,0 -10,10 Z">
  <animateMotion
     rotate="90" dur="6s" repeatCount="indefinite"
     path="M 30,40 c 0,-80 240,80 240,0 s -240,80 -240,0" />
</path>

<path d="M -10,-10 L 10,0 -10,10 Z">
  <animateMotion
     rotate="auto" dur="6s" repeatCount="indefinite"
     path="M 30,120 c 0,-80 240,80 240,0 s -240,80 -240,0" />
</path>

<path d="M -10,-10 L 10,0 -10,10 Z">
  <animateMotion
     rotate="auto-reverse" dur="6s" repeatCount="indefinite"
     path="M 30,200 c 0,-80 240,80 240,0 s -240,80 -240,0" />
</path>

キーフレームの制御

calcMode="discrete"

<circle cx="10" cy="10" r="10" fill="#c44">
  <animate
     attributeType="XML" attributeName="cx"
     values="10; 80; 150; 220; 290;"
     dur="3s" repeatCount="indefinite"
     calcMode="discrete" />
</circle>

calcMode="spline"

<circle cx="10" cy="10" r="10" fill="#c44">
  <animate
     attributeType="XML" attributeName="cx"
     dur="3s" repeatCount="indefinite"
     values="10; 290; 10" calcMode="spline"
     keySplines=".2,0 .8,.4; .2,.6 .8,1" />
</circle>

calcMode="paced"

<circle cx="10" cy="10" r="10" fill="#c44">
  <animate
     attributeType="XML" attributeName="cx"
     dur="3s" repeatCount="indefinite"
     values="10; 20; 150; 10" />
</circle>

<circle cx="10" cy="10" r="10" fill="#44c">
  <animate
     attributeType="XML" attributeName="cx"
     dur="3s" repeatCount="indefinite"
     values="150; 160; 290; 150"
     calcMode="paced" />
</circle>

keyTimesの効果

<circle cx="10" cy="10" r="10" fill="#c44">
  <animate
     attributeType="XML" attributeName="cx"
     dur="3s" repeatCount="indefinite"
     values="10; 20; 150; 10"
     keyTimes="0; .03; .5; 1" />
</circle>

animateMotionへのKeyTimesの適用

<circle cx="0" cy="0" r="10" fill="#c44">
  <animateMotion
     dur="3s" repeatCount="indefinite"
     path="M 10,10 l 280,0 0,30 -280,0 Z"
     calcMode="linear"
     keyPoints="0; 0.5; 1"
     keyTimes="0; 0.3; 1" />
</circle>

開始タイミングの制御

ドキュメント表示開始からのオフセット

<circle cx="10" cy="10" r="10" fill="#c44">
  <animate
     attributeType="XML" attributeName="cx"
     dur="6s" values="10; 290; 10"
     repeatCount="indefinite" />
</circle>

<circle cx="10" cy="30" r="10" fill="#44c">
  <animate
     attributeType="XML" attributeName="cx"
     dur="6s" values="10; 290; 10"
     begin="3s" repeatCount="indefinite" />
</circle>

負のオフセット

<circle cx="10" cy="10" r="10" fill="#c44">
  <animate
     attributeType="XML" attributeName="cx"
     dur="6s" values="10; 290; 10"
     repeatCount="indefinite" />
</circle>

<circle cx="10" cy="30" r="10" fill="#44c">
  <animate
     attributeType="XML" attributeName="cx"
     dur="6s" values="10; 290; 10"
     begin="-3s" repeatCount="indefinite" />
</circle>

他のアニメーションの終了と同時に開始

<circle cx="10" cy="10" r="10" fill="#c44">
  <animate
     attributeType="XML" attributeName="cx"
     dur="3s" from="10" to="290"
     id="s271" begin="0s; s272.end"
     fill="freeze" />
  <animate
     attributeType="XML" attributeName="cx"
     dur="3s" from="290" to="10"
     id="s272" begin="s271.end+1s" />
</circle>

特定のリピート回数で開始

<circle cx="10" cy="10" r="10" fill="#c44">
  <animate repeatCount="3"
           attributeType="XML" attributeName="cx"
           dur="6s" values="10; 290; 10"
           id="s28" begin="0s; s28.end" />

  <set attributeType="XML" attributeName="fill"
       begin="s28.begin" to="#c44" />

  <set attributeType="XML" attributeName="fill"
       begin="s28.repeat(1)" to="#44c" />

  <set attributeType="XML" attributeName="fill"
       begin="s28.repeat(2)" to="#4c4" />
</circle>

リンクによる開始

Click Me!
<circle cx="10" cy="10" r="10" fill="#c44">
  <animate
     attributeType="XML" attributeName="cx"
     dur="3s" values="10; 190; 10"
     id="s29" begin="indefinite" />
</circle>

<a xlink:href="#s29">
  <rect x="200" y="1" width="99" height="30"
        rx="4" ry="4" stroke="#c44" fill="#fee" />
</a>
<text x="210" y="21" pointer-events="none">
  Click Me!
</text>

DOMイベントによる開始

Click Me!
<circle cx="10" cy="10" r="10" fill="#c44">
  <animate
     attributeType="XML" attributeName="cx"
     dur="3s" values="10; 190; 10"
     begin="s30.mouseup" restart="whenNotActive" />
</circle>

<rect x="200" y="1" width="99" height="30"
      rx="4" ry="4" id="s30"
      stroke="#c44" fill="#fee" />
<text x="210" y="21" pointer-events="none">
  Click Me!
</text>

複数のアニメーション

異なる属性を同時にアニメーション

<circle cx="10" cy="10" r="10" fill="#c44">
  <animate
     attributeType="XML" attributeName="cx"
     dur="6s" values="10; 290; 10"
     repeatCount="indefinite" />
  <animate
     attributeType="XML" attributeName="fill"
     dur="5s" values="#c44; #44c; #c44"
     repeatCount="indefinite" />
</circle>

同じ属性に複数のアニメーションを適用

<circle cx="10" cy="10" r="10" fill="#c44">
  <animate
     attributeType="XML" attributeName="cx"
     dur="10s" values="10; 190; 10"
     repeatCount="indefinite" />
  <animate
     attributeType="XML" attributeName="cx"
     dur="1.3s" values="0; 100; 0"
     repeatCount="indefinite" additive="sum" />
</circle>

複数のanimateTransformを適用

<rect x="5" y="5" width="20" height="20"
      rx="4" ry="4" fill="#c44">
  <animateTransform
     attributeName="transform" attributeType="XML"
     type="translate" values="0,0; 275,0; 0,0"
     dur="6s" repeatCount="indefinite"
     additive="sum" />
  <animateTransform
     attributeName="transform" attributeType="XML"
     type="rotate" from="0 15,15" to="360 15,15"
     dur="4s" repeatCount="indefinite"
     additive="sum" />
</rect>

accumulate属性の効果

<circle cx="10" cy="50" r="10" fill="#c44">
  <animateMotion
     id="s34" dur="1s" path="M0,0 Q 30,-80 60,0"
     begin="0s; s34.end" repeatCount="5"
     accumulate="sum" />
</circle>

SVGフィルタの基礎

シンプルなフィルタ

<filter id="s35">
  <feGaussianBlur stdDeviation="2" />
</filter>

<image x="10" y="10" width="80" height="80"
       xlink:href="image01.jpg"
       filter="url(#s35)" />

フィルタの効果範囲

<filter id="s36">
  <feGaussianBlur stdDeviation="5" />
</filter>

<image x="10" y="10" width="80" height="80"
       xlink:href="image01.jpg"
       filter="url(#s36)" />

効果範囲の調整

<filter id="s37"
    x="-20%" y="-20%" width="140%" height="140%">
  <feGaussianBlur stdDeviation="5" />
</filter>

<image x="10" y="10" width="80" height="80"
       xlink:href="image01.jpg"
       filter="url(#s37)" />

オブジェクト座標系による効果の指定

<filter id="s38"
        primitiveUnits="objectBoundingBox">
  <feGaussianBlur stdDeviation="0.03" />
</filter>

<image x="10" y="10" width="80" height="80"
       xlink:href="image01.jpg"
       filter="url(#s38)" />
<image x="120" y="30" width="40" height="40"
       xlink:href="image01.jpg"
       filter="url(#s38)" />

複数のフィルタを組み合わせる

フィルタリング結果に別のフィルタをかける

<filter id="s39">
  <feColorMatrix type="hueRotate" values="45" />
  <feGaussianBlur stdDeviation="2" />
</filter>
<image x="10" y="10" width="80" height="80"
  xlink:href="image01.jpg" filter="url(#s39)" />

フィルタリング結果を重ねる

<feColorMatrix type="hueRotate"
               values="45" result="a" />
<feOffset dx="4" dy="4"
          in="SourceAlpha" result="b" />
<feMerge>
  <feMergeNode in="b" />
  <feMergeNode in="a" />
</feMerge>
</filter>

フィルタリング結果のブレンド

multiply screen darken lighten
<filter id="s41" x="0" y="0" width="270%" height="270%"
        primitiveUnits="objectBoundingBox">
  <feColorMatrix type="hueRotate" values="45" result="hue" />
  <feOffset dx="0.2" dy="0.2" in="SourceGraphic" result="ofs" />

  <feBlend mode="multiply" in="hue" in2="ofs" result="a" />
  <feBlend mode="screen" in="hue" in2="ofs" />
  <feOffset dx="1.5" dy="0" result="b" />
  <feBlend mode="darken" in="hue" in2="ofs" />
  <feOffset dx="0" dy="1.5" result="c" />
  <feBlend mode="lighten" in="hue" in2="ofs" />
  <feOffset dx="1.5" dy="1.5" result="d" />

  <feMerge>
    <feMergeNode in="a" /><feMergeNode in="b" />
    <feMergeNode in="c" /><feMergeNode in="d" />
  </feMerge>
</filter>

フィルタリング結果の合成

in out atop xor
<filter id="s42" x="0" y="0" width="270%" height="270%"
        primitiveUnits="objectBoundingBox">
  <feColorMatrix type="hueRotate" values="45" result="hue" />
  <feOffset dx="0.2" dy="0.2" in="SourceGraphic" result="ofs" />

  <feComposite operator="in" in="hue" in2="ofs" result="a" />
  <feComposite operator="out" in="hue" in2="ofs" result="b" />
  <feOffset dx="1.5" dy="0" result="b" />
  <feComposite operator="atop" in="hue" in2="ofs" result="c" />
  <feOffset dx="0" dy="1.5" result="c" />
  <feComposite operator="xor" in="hue" in2="ofs" result="d" />
  <feOffset dx="1.5" dy="1.5" result="d" />

  <feMerge>
    <feMergeNode in="a" /><feMergeNode in="b" />
    <feMergeNode in="c" /><feMergeNode in="d" />
  </feMerge>
</filter>

ライティング

Diffuseライティング

<filter id="s43">
  <feGaussianBlur stdDeviation="4" in="SourceAlpha" />
  <feDiffuseLighting surfaceScale="20" diffuseConstant="1"
                     lighting-color="white" result="d">
    <fePointLight x="250" y="-50" z="100" />
  </feDiffuseLighting>

  <feComposite operator="arithmetic" in="d" in2="SourceGraphic"
               k1="1" k2="0" k3="0.5" k4="0" result="r" />
</filter>

Specularライティング

<filter id="s44">
  <feGaussianBlur stdDeviation="4" in="SourceAlpha" />
  <feSpecularLighting surfaceScale="20" specularConstant="1"
      specularExponent="8" lighting-color="white" result="s">
    <fePointLight x="250" y="-50" z="100" />
  </feSpecularLighting>

  <feComposite operator="arithmetic" in="s" in2="SourceGraphic"
               k1="0" k2="1" k3="1" k4="0" result="r" />
  <feComposite operator="in" in="r" in2="SourceAlpha" />
</filter>

Diffuse+Specularライティング

<filter id="s45">
  <feGaussianBlur stdDeviation="4" in="SourceAlpha" result="h" />
  <feDiffuseLighting surfaceScale="20" diffuseConstant="1"
                     lighting-color="white" in="h" result="d">
    <fePointLight x="250" y="-50" z="100" />
  </feDiffuseLighting>

  <feSpecularLighting surfaceScale="20" specularConstant="1"
      specularExponent="8" lighting-color="white" in="h" result="s">
    <fePointLight x="250" y="-50" z="100" />
  </feSpecularLighting>

  <feComposite operator="arithmetic" in="d" in2="SourceGraphic"
               k1="1" k2="0" k3="0.5" k4="0" result="dd"/>
  <feComposite operator="arithmetic" in="dd" in2="s"
               k1="0" k2="1" k3="1" k4="0" result="ss" />
  <feComposite operator="in" in="ss" in2="SourceAlpha" />
</filter>

CSSの適用

styleタグとstyle属性によるCSS指定

<style><![CDATA[
  .red { fill:#f88; stroke:#c44; }
]]></style>

<circle class="red" cx="41" cy="41" r="40" />
<rect class="red" style="stroke-width:2;"
      x="50" y="40" width="80" height="50" />

外部スタイルシートによるCSS指定

<?xml-stylesheet href="style.css" type="text/css"?>
<svg xmlns="http://www.w3.org/2000/svg"
     xmlns:xlink="http://www.w3.org/1999/xlink"
     width="132" height="100">
  <circle class="blue" cx="41" cy="41" r="40" />
  <rect class="blue" style="stroke-width:2;"
        x="50" y="40" width="80" height="50" />
</svg>

JavaScriptによる制御

要素の取得と属性へのアクセス

<circle id="s48" cy="30" r="30" fill="#c44" />
<script><![CDATA[
  setInterval(function() {
    var f = +new Date % 2000 / 2000 * Math.PI * 2;
    var x = Math.sin(f) * 50 + 80;
    var el = document.getElementById('s48');
    el.setAttribute('cx', x);
  }, 100);
]]></script>

objectタグで読み込んだSVGへのアクセス

<object id="s49"
        type="image/svg+xml" data="js.svg" />
<script><![CDATA[
  var obj = document.getElementById('s49');
  obj.onload = function() {
    setInterval(function() {
      var doc = obj.contentDocument;
      var f = +new Date % 2000 / 1000 * Math.PI;
      var x = Math.sin(f) * 50 + 80;
      var el = doc.getElementById('circle');
      el.setAttribute('cx', x);
    }, 100); };
]]></script>

タグの動的生成

var ns = 'http://www.w3.org/2000/svg';
var svg = document.createElementNS(ns, 'svg');
svg.setAttribute('width',  '60');
svg.setAttribute('height', '60');

var c = document.createElementNS(ns, 'circle');
c.setAttribute('cx', '30');
c.setAttribute('cy', '30');
c.setAttribute('r',  '30');
c.setAttribute('fill', '#c44');

svg.appendChild(c);
document.getElementById('create').appendChild(svg);

イベント処理

<circle id="s51"
        cx="30" cy="30" r="30" fill="#c44" />
<script><![CDATA[
  var ctbl = {
    '#c44':'#4c4', '#4c4':'#44c', '#44c':'#c44'
  };
  var el = document.getElementById('s51');
  el.addEventListener('click', function(ev) {
    this.setAttribute('fill',
      ctbl[this.getAttribute('fill')]);
  }, false);
]]></script>