HTML5でサポートした <svg>
要素と、CSS、JavaScriptを組合せて、マウス処理する複雑な形の領域を作ります。次のような関東地方の地図のデモを作成しました。都道府県の形に沿ってマウスイベントが発火するのが、確認できるかと思います。
はじめに
HTML5でサポートした <svg>
要素により、HTMLドキュメント内にSVGを描画できるようになり、従来の矩形(<div>
など)だけでは難しかった複雑な形の要素も配置できるようになりました。SVG画像を描画するだけでなく、<svg> ... </svg>
内の要素(<path>
や <rect>
)に、これまでのHTML文章同様、CSSによるスタイルの指定や、JavaScriptによる要素の変更、イベントリスナの登録が可能となります。
これまで <area>
タグで指定していたマウスの処理の範囲も、SVGから作成することができます。SVGだとInkscapeのような視覚的にわかりやすいツールを使って、パスを作成できます。
HTMLの記述
HTMLに埋め込むSVGを用意するのは、Inkscapeを使うのが手っ取り早いです。SVGで適当なパスを作成し、出力ファイル形式をPlain SVGとしてファイルに書き出します。Plain SVGはInkscapeが使用するデータを削除したSVG形式です。しかしそれでも不要なメタ情報などが付与されるので、テキストエディタで削除してからHTMLに貼り付けます。
<!DOCTYPE html>
<html>
<body>
<svg width='240' height='262' >
<path data-name='Ibaraki' d='...' />
<path data-name='Chiba' d='...' />
<path data-name='Tokyo' d='...' />
<path data-name='Kanagawa' d='...' />
<path data-name='Tochigi' d='...' />
<path data-name='Gumma' d='...' />
<path data-name='Saitama' d='...' />
</svg>
</body>
</html>
各要素に指定される style
属性も、今回はCSSにから一括で指定するので削除します。InkscapeにはXMLエディタもついており、描画結果を確認しながら不要な要素の掃除もできて便利です。
data-name
属性には都道府県名を記述して、後にJavaScriptから参照します。
CSSの記述
続いてCSSでスタイルを記述します。CSSを使用すると他の要素と同様に、セレクタを指定してスタイルを設定できます。
path {
fill: #5fd35f;
stroke: #165016;
stroke-width: 1;
transition-duration: 200ms;
cursor: pointer;
}
path:hover {
fill: #2ca02c;
}
ここで fill
や stroke
など、普段見ないプロパティ名がたくさんあることに気づきます。これはSVGで使用するスタイルです。その他の使用可能なプロパティはW3Cから確認できます。
そして通常のHTMLドキュメント同様、path:hover
セレクタや transition-duration
プロパティも使用できます。これでCSSのみで、ホバー時に色の変化をつけることができました。
JavaScriptの記述
JavaScriptの記述も、従来のHTML要素と同じようにSVG内の要素を扱うことができます。
function alertName(e) {
alert('Welcome to ' + e.target.getAttribute('data-name'));
}
window.onload = function() {
paths = window.document.querySelectorAll('path');
for (i = 0; i < paths.length; ++i) {
paths[i].onclick = alertName;
}
};
window.onload
時に、すべての <path>
要素に対して、クリック時のイベントを記述しています。このイベント内では、ターゲットのdata-name
内のデータ参照し、 alert
で表示しています。
おわりに
SVGを使うことで、<area>
タグに変わる方法で、柔軟かつ容易にマウス処理の範囲を指定することができました。
ただ、CodePenで動作は確認できたのですが、HTMLの仕様として合法かどうかまでは確認できていないんので、仕様書をもう一度確認する必要があります。