2013年3月2日土曜日

svgを使って動かせる地図を作ろう

svgの特色としては「ベクタ画像である」「グラフィックの部品化が容易」「domを操作することで様々な処理を行うことが出来る」等,様々なものが挙げられますが,いざこれらを活かすとなるとどう使えば良いかイメージしにくいこともあろうかと思います.

そこで今回は実際にこれらの仕組みを使って簡単な地図を作ってみようと思います.でも単なる地図であれば面白くありませんから,拡大・縮小・移動・回転を可能とする言わばtiny google mapのような機能を実装してみましょう.


とにかく見てみよう


それでは早速見てみましょう.直接開く
地図画像
スクリプト

実装した機能は次のとおりです.
  • マウスドラッグで位置を変更できます
  • マウスホイールで拡大縮小できます
  • shiftもしくはaltキーを押したままマウスをホイールすることで回転することができます
  • ダブルクリックで位置を元に戻します
  • 地図を変形しても市名を表す文字列のサイズは変化しません
地図アプリとしては極めて簡易的なものですが,雰囲気は出ていると思います.
firefox/chrome/opera/safari/ie10で動作の確認をしました.

アプリの構造


アプリケーションの構造としてはソースを見てもらうと判る通り,次の3つのファイルから構成されています.
  • ベースとなるsvgファイル
  • 地図画像となるsvgファイル
  • アプリを構成するjsスクリプトファイル
ベースとなる地図画像と処理を行う部分とを分離しているため,管理を容易にしています.

スクリプトを組むのにライブラリは必要?


この地図アプリを作るにあたり,どのようなライブラリを使ったか気になった方には申し訳ありません.本スクリプトはpure SVGDOM+αで作られており,外部ライブラリは一切利用していません.
この手のライブラリとしてはd3.jsが有名ですが,高機能な反面シンプルに実装したい場合に困る場合があります.ライブラリ自体難解なものが多いですからね.

その点SVGDOMをよーく眺めてみると,非常によくできていることがわかります.今回使ったtransform周りのapiもその一つで,上手く使いこなせればsetAttribute/getAttributeだけでは難しかった処理を簡潔に記述することができます.

そう,無理にライブラリを選定する前に,一度SVGDOMのapiがどのような機能を備えているかを眺めて欲しい…というのが今回の隠れた主題でもあります.svgの内部的な動作を理解するためにもSVGDOMを学ぶことには非常に意義があります.

ブラウザ環境ごとの動作の違いが気になる?


確かにそのとおりで,ライブラリを利用することによりその差を吸収してくれる可能性はあります.が,レガシーieがsvgをサポートしていないのは論外としても,その他の環境では私の経験上さほど気になることはありませんでした(動作しないものはどうあがいても動かないなど,諦め甲斐がある…)

また今回のようにスタンドアロンのsvgに直接スクリプトを挿入する場合は,そもそもライブラリが利用できません!(ほとんどがインラインsvgでの利用を想定しているため)

よって,場合によってはSVGDOMを使わざるを得ないケースもあるのです.

tips


以下,今回のアプリを作るに当たって注意した点について列挙します.詳しくはソースコードを見てください.
  • ieではuse要素による外部図形の参照ができない.
    その為,地図画像をXMLHttpRequestで別途取得しています.
  • ieではSVGTransformオブジェクトを生成しただけでは有効とはならず,一度要素に追加してから取得し直す必要がある.
  • SVGMatrixには様々なメソッドが提供されているものの,メソッドを実行するたびにSVGMatrixオブジェクトを生成するため,イベント処理に組み込むには不適.その為,独自に行列計算を行うスクリプトを組んでいる.
  • 地名情報と地図情報とでは予め座標の位置を揃えておく必要がある. 
  • (今は使ってないけれど) firefoxでuse要素をshiftキーを押しながらクリックすると,なぜか新しいウインドウが開いて,その中にuse要素が参照している画像が表示される.(バグ?)
  • chromeではshiftキーを押しながらマウスダウンすると,後続するmouseupイベントが発生しない!(htmlでは発生せず,スタンドアロンのsvgでのみ発現する) 

返答(yahooアカウントもってないだよ)

  • ieでdominant-baseline属性がおかしくね?
    http://detail.chiebukuro.yahoo.co.jp/qa/question_detail/q14121736264
    → おかしいのならおかしいのでしょう.
    おそらくはieがdominant-baseline:centralをサポートしていないのかも知れません.
    middleに変えてみるか,思い切ってdominant-baseline属性を削除して試して下さい.
    この場合,大体文字の下辺から数ピクセルの位置がテキストの描画基準座標となるので,その分テキストの位置を下にずらすなりして調整すると良いでしょう.
    (動作上はそれほど気にならないかと思います.)
    svgのサポート状況はブラウザ毎にまちまちで,中々思い通りに行きませんorz...

    0 件のコメント:

    コメントを投稿