LoginSignup
3
3

More than 1 year has passed since last update.

SVGで日本地図のエリア別にホバー処理できるようにする

Posted at

こんにちは、ウェブエンジニアのmasakichiです。
需要があるかわからない程度のtipsなどを書いています。

今回はSVGを利用して、地図のエリアごとにをホバー処理させるという実装をしました。(説明むずい)

完成形はこちらです

ちょっと何言ってんのわからないと思いますので、こんな感じです↓

See the Pen Untitled by masakichi (@masakichi) on CodePen.

なぜSVGを使うのか?

通常のpng画像などだとhover時の選択範囲をうまく指定できずに、意図した挙動になりません。
しかしSVGで作ったデータならpathの範囲内ごとにしっかりとhoverを当てることができます。

では実際に作り方を順番に書いていきます。

SVGデータを作る

まずイラレからSVGデータをつくり書き出します。
今回はフリー素材の日本地図を使いました。
下記のように九州エリアなどpathが離れてしまっているところは、グルーピングしておきます。
sample.png

SVGを貼り付ける

書き出したSVGデータをHTMLファイルに貼り付けます。
ただこれだと、すごく見づらいので整形します。

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>タグなどがあったら削除しておく

整形したのがこちら。だいぶ見やすくなりました。

HTML
<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ファイルで管理します。

SCSS
svg{
    display: block;
    max-width: 400px;
    margin: 0 auto;
    .maps{
        fill:#1eaa39;
        transition: fill .3s;
    }
}

色を変えるためのclassを追加

.mapsクラスに.activeクラスがついたら色が変わるようにCSSを追記します

SCSS
svg{
    display: block;
    max-width: 400px;
    margin: 0 auto;
    .maps{
        fill:#1eaa39;
        transition: fill .3s;
    }
    //activeクラスがついたら色を変更
    .maps.active{
        fill:#f5f825;
    }
}

JSでクラス付け替え処理を追加

ホバー時のactiveクラス付け替えはjavascriptで実装します

JavaScript
$(function(){
    let maps = $('#japan').find('.maps');
    maps.mouseenter(function(){
        $(this).addClass('active');
    })
    maps.mouseleave(function(){
        $(this).removeClass('active');
    })
});

これでホバー時に色が変わるようになりました。
次は地図の下に、それぞれのエリア名を表示します。

エリア名表示のためにタグを追加

まず、svgの下にエリア名を表示させる<p>タグを追加します。
またmapsクラスにはエリア名を持ったデータ属性を与えておきます。

HTML
<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で記述すれば完成です。

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って便利ですね!
もっといろんなことできそうなので、どこかのタイミングで勉強したいと思います。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3