ホーム > X-Plus > XML Square >  デベロッパーズコーナー  >  実践!SVG

この記事を送る はてなブックマークに追加する BuzzurlにブックマークBuzzurlにブックマーク Yahoo!ブックマークに登録
テキストリンクコードを取得する

デベロッパーズコーナー:実践!SVG(3)

2002年11月20日作成 

実践!SVG
第3回:DOM+JavaScriptでSVGの表示をダイナミックに変更しよう!
   

株)日本ユニテック
青木 秀起

1.イントロダクション

本連載第1回では、SVGグラフィックを動かすにはSMIL AnimationとDOMの2つの方法があり、SMIL Animationの書き方を簡単に解説しました。第3回では、DOM+JavaScriptでSVG表示を変更したり動かしたりする方法を紹介します。

Adobe社の「SVG Viewer」をIEにプラグインして使います。Adobe社のダウンロードサイトからダウンロードしてください。指定されたインストール手順に従うと、IEにプラグインされます。

2.スクリプトの書き方

SVGファイル中にスクリプトを書き込むには、以下の2つの方法があります。

①<script>部分にスクリプトを書く

<script>部分にスクリプト言語を書き込みます。

<script>要素の書き方
<svg width="100" height="100">
<script type="text/ecmascript">
・・・・・・コーディング・・・・・・
</script>
・・・・・・SVG要素・・・・・・
</svg>

<svg>要素中のcontentScriptType属性にデフォルトのスクリプト言語を指定しておくことができます。デフォルト値は"text/ecmascript"なので、何も指定しないと"text/ecmascript"になります。また、<script>要素のtype属性に個々のスクリプト言語を指定することもできます。<script>要素は、HTMLの<script>要素と同じように、スクリプトを書くための場所を表します。

SMIL AnimationをSVG用に拡張したものが以下のものです。

ECMAScriptは、標準化団体ECMAが1997年7月にECMA-262として策定したスクリプト言語です。競合していた2つの言語、Netscape社のJavaScriptとMicrosoft社のJScriptとを融合したものです。現在のバージョンは、1999年12月に公開された"3rd edition"です。


②イベント属性に対応するスクリプトをSVG要素中に直接書く

SVGでは、"onclick"や"onmouseover"などのイベント属性をSVG要素中に書き、イベントに対応した処理を行わせることができます。

SVG要素中の書き方
(1) <rect onclick="create_obj(evt)" x="100" y="100" width="200" height="50" />
    =>マウスをクリックすると、スクリプト中で定義されたcreate_obj(evt)関数が呼び出される。
(2) <rect x="100" y="100" width="200" height="50" fill="none" onmouseover="evt.target.setAttribute('fill', 'red')"/>
    =>矩形の上をマウスが通過すると、矩形が赤に塗りつぶされる。

多くの場合、最初の例のようにスクリプト中で定義された関数を呼び出すためにイベント属性が使われますが、2番目の例のように属性の中に直接JavaScriptのコマンドを書くこともできます。2番目の例では、DOMのsetAttribute()メソッドを使用しています。

SVGは、以下のイベント属性をサポートしています。

表1 SVG要素中で使用できるイベント属性
イベント属性
イベント発生時
グラフィック要素とコンテナ要素のイベント属性
onfocusin 要素がフォーカスされたとき
onfocusout 要素のフォーカスが解除されたとき
onactivate 要素がアクティブになったとき
onclick クリックされたとき
onmousedown 要素上でポインティング・デバイスのボタンが押されたとき
onmouseup 要素上でポインティング・デバイスのボタンが放されたとき
onmouseover 要素内にポインティング・デバイスが移動してきたとき
onmousemove 要素上でポインティング・デバイスが移動しているとき
onmouseout 要素外にポインティング・デバイスが去ったとき
onload 要素と子孫を完全に解析し、その要素の処理に入るとき
ドキュメント・レベルのイベント属性
onunload DOMインプリメンテーションがドキュメントをウィンドウやフレームから削除したとき
onabort 要素のロードが完全に終了する前にページロードが停止したとき
onerror 要素が正しくロードされなかった場合やスクリプト実行中にエラーが発生した場合
onresize ドキュメント表示のサイズが変更された場合
onscroll ドキュメント表示がX方向またはY方向に、あるいはその両方向にシフトしたとき
onzoom ドキュメントがズームレベルをユーザー操作に応じて変更するとき
アニメーション・イベント属性
onbegin アニメーション要素が開始したとき
onend アニメーション要素が終了したとき
onrepeat アニメーション要素が繰り返すとき

3.DOM+JavaScriptでSVGグラフィックを変更する

では実際に、DOMによりグラフィックをダイナミックに変更するスクリプトを書いてみましょう。

①色や大きさを変更する

簡単な矩形を表す次のファイルをベースに考えてゆきます。

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="12cm" height="10cm">
<rect x="2cm" y="2cm" width="8cm" height="6cm" rx="50" ry="50" fill="blue" stroke="blue"/>
</svg>

これは、青色に塗りつぶされた矩形を表します。この矩形をクリックすると赤色の塗りつぶしに変わるように書き換えてみましょう。

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="12cm" height="10cm">
<rect onclick="evt.target.setAttribute('fill', 'red')" x="2cm" y="2cm" width="8cm" height="6cm" rx="50" ry="50" fill="blue" stroke="blue"/>
</svg>

このサンプルでは、DOMのElementオブジェクトのsetAttributeNode()メソッドを使用し、クリックされたら"fill"属性の属性値を"red"に変更するようにしています。

サンプルファイル1

ではさらに、塗りつぶしの色だけでなく矩形の大きさも変更してみましょう。JavaScriptでは、複数のコマンドを書き込むときにはセミコロン(";")で分離して書くことができます。

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="12cm" height="10cm">
<rect onclick="evt.target.setAttribute('fill', 'red');evt.target.setAttribute('width', '4cm');evt.target.setAttribute('height', '3cm')" x="2cm" y="2cm" width="8cm" height="6cm" rx="50" ry="50" fill="blue" stroke="blue"/>
</svg>

サンプルファイル2

このように簡単なスクリプトであればイベント属性の値に直接書き込むことができます。一方、複雑な処理を行わせたい場合には<script>部分に処理を定義した関数を書き、それを呼び出す必要があります。たとえば、「サンプルファイル1」で、クリックするたびに色を変更したり元に戻したりしたい場合、次のように書きます。

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="12cm" height="10cm">
  <script type="text/ecmascript">
    <![CDATA[
      function click_colorsize(evt)
        {
        var color = evt.target;
        var currentcolor = color.getAttribute("fill");
        if (currentcolor == "blue")
          color.setAttribute("fill", "red");
        else
          color.setAttribute("fill", "blue");
        }
    ]]>
  </script>
<rect onclick="click_colorsize(evt)" x="2cm" y="2cm" width="8cm" height="6cm" rx="50" ry="50" fill="blue" stroke="blue"/>
</svg>

サンプルファイル3

②同じ形のグラフィックを作成する

①と同じような要領で、クリックするたびに同じ形の矩形を少しずつずらして作成してゆくサンプルを書いてみましょう。

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg id="rect" width="400" height="200">
<script>
<![CDATA[
var n=0;
function clone_obj(evt)
  {
    svgdoc=evt.getTarget().getOwnerDocument();n=n+1;
    obj=svgdoc.getElementById("original");
    var newnode = obj.cloneNode(false);
    newnode.setAttribute ("x",20+10*n/2);
    newnode.setAttribute ("y",20+10*n/2);
    var contents = svgdoc.getElementById ('rect');
    newnode = contents.appendChild (newnode);
  }
]]>
</script>
<rect id="original" onclick="clone_obj(evt)" x="20" y="20" width="180" height="80" rx="50" ry="50" fill="blue" stroke="yellow"/>
</svg>

サンプルファイル4

上のサンプルでは、以下のDOMメソッドが使われています。

getElementById()・・・・・id属性によって特定の要素を取り出す
cloneNode()・・・・・・・・ノードをコピーする
setAttribute()・・・・・・・新しく生成されたオブジェクトに属性を結びつける
appendChild()・・・・・・・newChildを子ノードの最後に加える

③グラフィックを回転させる

次に、クリックするたびにグラフィックを少しずつ右回転させてみましょう。

<?xml version="1.0" standalone="no"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN" "http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
<svg width="600" height="300">
<script>
<![CDATA[
  var angle=0;
  function trans_obj(evt)
    {
      svgdoc=evt.getTarget().getOwnerDocument();
      angle=angle+0.5;
      objet=svgdoc.getElementById("rect");
      transm="matrix("+Math.cos(angle)+" "+Math.sin(angle)+""+(-1*Math.sin(angle))+" "+Math.cos(angle)+"300 150)";
      objet.setAttribute ("transform",transm);
    }
]]>
</script>
<rect id="rect" onclick="trans_obj(evt)" x="-75" y="-50" width="150" height="100" fill="blue" stroke="yellow" transform="matrix(1 0 0 1 300 150)"/>
</svg>

サンプルファイル5

このサンプルファイルは、クリックするたびに(300,150)を中心にして回転します。"angle=angle+0.5"でクリックするたびに角度を増やしてゆき、その角度に応じた値をtransform属性のそれぞれの値に設定してゆきます。
matrix(cos(a) sin(a) -sin(a) cos(a) 300 150)は、座標軸を(300,150)を中心にaだけ回転させることを表します。

④カーソルの移動に合わせてグラフィックを移動する

最後に、カーソル位置の移動に合わせてグラフィックも移動してゆくサンプルを考えてみましょう。

<?xml version="1.0"?>
<!DOCTYPE svg PUBLIC
"-//W3C//DTD SVG 20001102//EN"
"http://www.w3.org/TR/2000/CR-SVG-20001102/DTD/svg-20001102.dtd">
<svg width="600" height="400" onload="getRect()" onmousemove="movedXY(evt)">
<script>
  <![CDATA[
    function getRect()
      {
        move = document.getElementById("movec");
      }
    function moveCursor(currentx,currenty)
      {
        move.setAttribute("x", currentx);
        move.setAttribute("y", currenty);
      }
    function movedXY(e)
      {
        var currentx = e.getClientX();
        var currenty = e.getClientY();
        setTimeout('moveCursor('+currentx+','+currenty+')',10);
      }

]]>
</script>
<rect width="100%" height="100%" style="opacity:0;"/>
<rect id="movec" fill="blue" width="20" height="20" />
</svg>

サンプルファイル6

上の例では、getClientX()とgetClientY()で現在のカーソルの位置を取得し、それをsetAttribute()メソッドで矩形の座標に設定しています。setTimeout('実行する命令',時間)は、指定された時間後に命令を実行します。この例では、"10"の数値を大きくすると反応が遅くなり、小さくすると早くなります。

4.まとめ

SVGは、単なるベクタ・グラフィック記述言語であるにとどまらず、DOMやJavaScriptと組み合わせて使うことでダイナミックで対話的な処理を可能にします。新しいWebアプリケーション開発を可能にする、Webグラフィック標準となることが期待されています。




関連サービス

IT技術およびIT製品の可用性調査・検証業務





ページトップへ戻る