こんにちは、ウェブエンジニアのmasakichiです。
需要があるかわからない程度のtipsなどを書いています。
今回はSVGを利用して、地図のエリアごとにをホバー処理させるという実装をしました。(説明むずい)
完成形はこちらです
ちょっと何言ってんのわからないと思いますので、こんな感じです↓
See the Pen Untitled by masakichi (@masakichi) on CodePen.
#なぜSVGを使うのか?
通常のpng画像などだとhover時の選択範囲をうまく指定できずに、意図した挙動になりません。
しかしSVGで作ったデータならpathの範囲内ごとにしっかりとhoverを当てることができます。
では実際に作り方を順番に書いていきます。
#SVGデータを作る
まずイラレからSVGデータをつくり書き出します。
今回はフリー素材の日本地図を使いました。
下記のように九州エリアなどpathが離れてしまっているところは、グルーピングしておきます。
#SVGを貼り付ける
書き出したSVGデータをHTMLファイルに貼り付けます。
ただこれだと、すごく見づらいので整形します。
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1269.31 1104.19"><defs><style>.cls-1{fill:#1eaa39;}</style></defs><g id="レイヤー_2" data-name="レイヤー 2"><g id="日本"><path id="北海道" class="cls-1" d="M1224.16,0H959.11A45.29,45.29,0,0,0,914,45.15V257.93a35.43,35.43,0,0,0,35.33,35.32h56.53a35.43,35.43,0,0,0,35.33-35.32,21.64,21.64,0,0,1,.25-3.32c.53-3.39,2.07-10.14,6.26-14.57,4.76-5,15.06-4.55,15.06-4.55h161.44a45.29,45.29,0,0,0,45.15-45.15V45.15A45.29,45.29,0,0,0,1224.16,0Z"/><g id="九州"><path class="cls-1" d="M60.52,948.89H22.44C10.1,948.89,0,961.46,0,976.82v99.45c0,15.36,10.1,27.92,22.44,27.92H60.52c12.34,0,22.44-12.56,22.44-27.92V976.82C83,961.46,72.86,948.89,60.52,948.89Z"/><path class="cls-1" d="M294,661.82H173.76c-31.7,0-57.65,24.55-57.65,54.56l-.27,313.76c0,16.13,13.95,29.33,31,29.33h99.59c17.05,0,31-13.2,31-29.33v-25c0-20.75,6.78-24.39,17.19-24.39h5.09c40.85,0,52-16,52-54.56V716.38C351.66,686.37,325.72,661.82,294,661.82Z"/></g><rect id="四国" class="cls-1" x="386.34" y="858.25" width="229.75" height="138.76" rx="22.98"/><g id="本州"><path class="cls-1" d="M1172.21,270.46h-64.49a32.94,32.94,0,0,0-32.85,32.85v24.91a13.2,13.2,0,0,1-3.59,9.41c-4,4-11.26,3.67-11.26,3.67H958.76A44.93,44.93,0,0,0,914,386.1V605.36a17.34,17.34,0,0,1-5.32,13.11c-6.08,6.08-14.47,5.33-14.47,5.33H818.71s-15.05.8-20.79-4.95c-6.22-6.21-5.68-18-5.68-18V586.32a40.8,40.8,0,0,0-40.69-40.68H741a40.79,40.79,0,0,0-40.68,40.68v17.8s.39,6.26-6.52,13.17-13.21,6.51-13.21,6.51H436.06a49.86,49.86,0,0,0-49.72,49.72V799a26.75,26.75,0,0,0,26.74,26.75H602.14A50.48,50.48,0,0,1,652.47,876v94.23A26.74,26.74,0,0,0,679.21,997h295.1a15.12,15.12,0,0,0,15.13-15.13V966.42c0-15.36-4.2-46.9,30.85-46.9h45.48a41.77,41.77,0,0,1,41.65,41.64V981s-.25,8.36,3.68,12.28,11.35,3.69,11.35,3.69h32.89a49.86,49.86,0,0,0,49.72-49.72v-644A32.94,32.94,0,0,0,1172.21,270.46Z"/><rect class="cls-1" x="818.92" y="534.05" width="64.83" height="61.35" rx="18.52"/></g></g></g></svg>
#SVGのコードを整形する
以下の点に注意しながら整形します
- タグごとに改行つける
-
<defs>
タグのstyleはCSSへ転機 - 北海道、九州、四国、本州のそれぞれのエリアごとに
<g>
タグでグループ化しておく - 不要な
<g>
タグなどがあったら削除しておく
整形したのがこちら。だいぶ見やすくなりました。
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1269.31 1104.19">
<g id="japan">
<g id="hokkaido" class="maps">
<path d="M1224.16,0H959.11A45.29,45.29,0,0,0,914,45.15V257.93a35.43,35.43,0,0,0,35.33,35.32h56.53a35.43,35.43,0,0,0,35.33-35.32,21.64,21.64,0,0,1,.25-3.32c.53-3.39,2.07-10.14,6.26-14.57,4.76-5,15.06-4.55,15.06-4.55h161.44a45.29,45.29,0,0,0,45.15-45.15V45.15A45.29,45.29,0,0,0,1224.16,0Z"/>
</g>
<g id="kyushu" class="maps">
<path d="M60.52,948.89H22.44C10.1,948.89,0,961.46,0,976.82v99.45c0,15.36,10.1,27.92,22.44,27.92H60.52c12.34,0,22.44-12.56,22.44-27.92V976.82C83,961.46,72.86,948.89,60.52,948.89Z"/>
<path d="M294,661.82H173.76c-31.7,0-57.65,24.55-57.65,54.56l-.27,313.76c0,16.13,13.95,29.33,31,29.33h99.59c17.05,0,31-13.2,31-29.33v-25c0-20.75,6.78-24.39,17.19-24.39h5.09c40.85,0,52-16,52-54.56V716.38C351.66,686.37,325.72,661.82,294,661.82Z"/>
</g>
<g id="shikoku" class="maps">
<rect x="386.34" y="858.25" width="229.75" height="138.76" rx="22.98"/>
</g>
<g id="honshu" class="maps">
<path d="M1172.21,270.46h-64.49a32.94,32.94,0,0,0-32.85,32.85v24.91a13.2,13.2,0,0,1-3.59,9.41c-4,4-11.26,3.67-11.26,3.67H958.76A44.93,44.93,0,0,0,914,386.1V605.36a17.34,17.34,0,0,1-5.32,13.11c-6.08,6.08-14.47,5.33-14.47,5.33H818.71s-15.05.8-20.79-4.95c-6.22-6.21-5.68-18-5.68-18V586.32a40.8,40.8,0,0,0-40.69-40.68H741a40.79,40.79,0,0,0-40.68,40.68v17.8s.39,6.26-6.52,13.17-13.21,6.51-13.21,6.51H436.06a49.86,49.86,0,0,0-49.72,49.72V799a26.75,26.75,0,0,0,26.74,26.75H602.14A50.48,50.48,0,0,1,652.47,876v94.23A26.74,26.74,0,0,0,679.21,997h295.1a15.12,15.12,0,0,0,15.13-15.13V966.42c0-15.36-4.2-46.9,30.85-46.9h45.48a41.77,41.77,0,0,1,41.65,41.64V981s-.25,8.36,3.68,12.28,11.35,3.69,11.35,3.69h32.89a49.86,49.86,0,0,0,49.72-49.72v-644A32.94,32.94,0,0,0,1172.21,270.46Z"/><rect class="cls-1" x="818.92" y="534.05" width="64.83" height="61.35" rx="18.52"/>
</g>
</g>
</svg>
スタイリングはCSSファイルで管理します。
svg{
display: block;
max-width: 400px;
margin: 0 auto;
.maps{
fill:#1eaa39;
transition: fill .3s;
}
}
#色を変えるためのclassを追加
.maps
クラスに.active
クラスがついたら色が変わるようにCSSを追記します
svg{
display: block;
max-width: 400px;
margin: 0 auto;
.maps{
fill:#1eaa39;
transition: fill .3s;
}
//activeクラスがついたら色を変更
.maps.active{
fill:#f5f825;
}
}
#JSでクラス付け替え処理を追加
ホバー時のactiveクラス付け替えはjavascriptで実装します
$(function(){
let maps = $('#japan').find('.maps');
maps.mouseenter(function(){
$(this).addClass('active');
})
maps.mouseleave(function(){
$(this).removeClass('active');
})
});
これでホバー時に色が変わるようになりました。
次は地図の下に、それぞれのエリア名を表示します。
#エリア名表示のためにタグを追加
まず、svgの下にエリア名を表示させる<p>
タグを追加します。
またmaps
クラスにはエリア名を持ったデータ属性を与えておきます。
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1269.31 1104.19">
<g id="japan">
<g id="hokkaido" data-area="北海道" class="maps"><!-- データ属性追加 -->
<path d="M1224.16,0H959.11A45.29,45.29,0,0,0,914,45.15V257.93a35.43,35.43,0,0,0,35.33,35.32h56.53a35.43,35.43,0,0,0,35.33-35.32,21.64,21.64,0,0,1,.25-3.32c.53-3.39,2.07-10.14,6.26-14.57,4.76-5,15.06-4.55,15.06-4.55h161.44a45.29,45.29,0,0,0,45.15-45.15V45.15A45.29,45.29,0,0,0,1224.16,0Z"/>
</g>
<g id="kyushu" data-area="九州" class="maps"><!-- データ属性追加 -->
<path d="M60.52,948.89H22.44C10.1,948.89,0,961.46,0,976.82v99.45c0,15.36,10.1,27.92,22.44,27.92H60.52c12.34,0,22.44-12.56,22.44-27.92V976.82C83,961.46,72.86,948.89,60.52,948.89Z"/>
<path d="M294,661.82H173.76c-31.7,0-57.65,24.55-57.65,54.56l-.27,313.76c0,16.13,13.95,29.33,31,29.33h99.59c17.05,0,31-13.2,31-29.33v-25c0-20.75,6.78-24.39,17.19-24.39h5.09c40.85,0,52-16,52-54.56V716.38C351.66,686.37,325.72,661.82,294,661.82Z"/>
</g>
<g id="shikoku" data-area="四国" class="maps"><!-- データ属性追加 -->
<rect x="386.34" y="858.25" width="229.75" height="138.76" rx="22.98"/>
</g>
<g id="honshu" data-area="本州" class="maps"><!-- データ属性追加 -->
<path d="M1172.21,270.46h-64.49a32.94,32.94,0,0,0-32.85,32.85v24.91a13.2,13.2,0,0,1-3.59,9.41c-4,4-11.26,3.67-11.26,3.67H958.76A44.93,44.93,0,0,0,914,386.1V605.36a17.34,17.34,0,0,1-5.32,13.11c-6.08,6.08-14.47,5.33-14.47,5.33H818.71s-15.05.8-20.79-4.95c-6.22-6.21-5.68-18-5.68-18V586.32a40.8,40.8,0,0,0-40.69-40.68H741a40.79,40.79,0,0,0-40.68,40.68v17.8s.39,6.26-6.52,13.17-13.21,6.51-13.21,6.51H436.06a49.86,49.86,0,0,0-49.72,49.72V799a26.75,26.75,0,0,0,26.74,26.75H602.14A50.48,50.48,0,0,1,652.47,876v94.23A26.74,26.74,0,0,0,679.21,997h295.1a15.12,15.12,0,0,0,15.13-15.13V966.42c0-15.36-4.2-46.9,30.85-46.9h45.48a41.77,41.77,0,0,1,41.65,41.64V981s-.25,8.36,3.68,12.28,11.35,3.69,11.35,3.69h32.89a49.86,49.86,0,0,0,49.72-49.72v-644A32.94,32.94,0,0,0,1172.21,270.46Z"/><rect class="cls-1" x="818.92" y="534.05" width="64.83" height="61.35" rx="18.52"/>
</g>
</g>
</svg>
<p id="areaName"></p><!-- ここにエリア名を出す -->
#JSにエリア名表示の処理を追加
最後にエリア名の取得と表示をJavaScriptで記述すれば完成です。
$(function(){
let maps = $('#japan').find('.maps');
maps.mouseenter(function(){
$(this).addClass('active');
let areaName = $(this).data('area');
$('#areaName').text(areaName);
})
maps.mouseleave(function(){
$(this).removeClass('active');
$('#areaName').text("");
})
});
SVGって便利ですね!
もっといろんなことできそうなので、どこかのタイミングで勉強したいと思います。