Leafletで地図を作ろう - (富嶽三十六景浮世絵マップ)

1.富嶽三十六景浮世絵マップ

作品例として、富嶽三十六景浮世絵マップを作成します。この題材は葛飾北斎の富嶽三十六景の浮世絵を利用して 浮世絵が書かれた場所と思われる所にアイコン画像マーカーを配置しています。 マーカーをクリックするとポップアップに広重の浮世絵画像と浮世絵名や場所などを表示します。 ソースコードの大部分は、すでに公開している「気象庁震度観測点マップ」からの流用です。内容が重複するので「気象庁震度観測点マップ」で説明していない 追加、変更部分のみを中心に説明していきます。
浮世絵の画像素材は、下記サイト様にて提供されているものを利用させて頂きました。

取得先 : 著作権フリー作品「富嶽三十六景」

2.ソースコードの説明

富嶽三十六景浮世絵マップのメインとなる(toukaidou.html)コードです。各実装部品の定義ファイル類は外部ファイルとしています。 leaflet.css、all.css、fugaku.css、leaflet.js、SlideMenu.js、fugaku.js、fugakuidef.jsライブラリ等をヘッダー部分に指定しています。 fugaku.cssとfugaku.js、fugakuef.jsは筆者が作成したものです。

DEMO

fugaku.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
<!DOCTYPE html>
<html lang="ja">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>富嶽三十六景浮世絵マップ</title>
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.6.0/dist/leaflet.css"
  integrity="sha512-xwE/Az9zrjBIphAcBb3F6JVqxf46+CDLwfLMHloNu6KEQCAWi6HcDUbeOfBIptF7tcCzusKFjFw2yuvEpDL9wQ=="
  crossorigin=""/>
<script src="https://unpkg.com/leaflet@1.6.0/dist/leaflet.js"
  integrity="sha512-gZwIG9x3wUXg2hdXF6+rVkLF/0Vi9U8D2Ntg4Ga5I5BZpVkVxlJWbSQtXPSiUTtC0TjtGOmxa1AJPuV0CPthew=="
  crossorigin=""></script>
<link rel="stylesheet" type="text/css" media="screen" href="./css/fugaku.css">
<link rel="stylesheet" href="./css/L.Control.SlideMenu.css" />
<link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.0.13/css/all.css"
   integrity="sha384-DNOHZ68U8hZfKXOrtjWvjxusGo9WQnrNx2sqG0tfsghAvtVlRW3tvkXWZh58N9jp" crossorigin="anonymous">
<script src="./jsscr/L.Control.SlideMenu.js"></script>
<script src='./jsscr/fugaku.js'></script>
<script src='./jsscr/fugakudef.js'></script>
<script>
  var markers=[];
 
  function init(){
      //***** 中心基準座標の指定 *****
      var mpoint = [35.56798, 138.68866];
      var map = L.map('mapcontainer').setView(mpoint, 9);
 
      //***** 3つの地図タイルを設定 *****
      var gsi =L.tileLayer('https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png',
          { attribution: "<a href='https://maps.gsi.go.jp/development/ichiran.html' target='_blank'>地理院タイル</a>"});
      var gsipale = L.tileLayer('http://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png',
          { attribution: "<a href='https://maps.gsi.go.jp/development/ichiran.html' target='_blank'>地理院タイル</a>"});
      var osm = L.tileLayer('http://tile.openstreetmap.jp/{z}/{x}/{y}.png',
          { attribution: "<a href='http://osm.org/copyright' target='_blank'>OpenStreetMap</a> contributors" });
      //***** baseMapsオブジェクトのプロパティに3つのタイルを設定 *****
      var baseMaps = {
            "地理院地図" : gsi,
            "淡色地図" : gsipale,
            "オープンストリートマップ"  : osm
      };
      L.control.layers(baseMaps).addTo(map);
      osm.addTo(map);
 
      //***** Slide Menu Content html *****
      var header1  = '<span class="cstm-slidmenu-header" style=" background-color: #0033aa">浮世絵名を選択</span>';
      var contents1  = '<select class="combinfo-set" name="select" onchange="selText(this);">';
          for(var i=0;i<selbox.length;i++){
                if (i==0) {
                    contents1 += '<option disabled selected value=' + selbox[i].val + '>' + selbox[i].name + '</option>';
                    }else{
                    contents1 += '<option  value=' + selbox[i].val + '>' + selbox[i].name + '</option>';
                }
          }
          contents1 += '</select>';
      var contents2  = '<br><br>';
 
      var header3  = '<span class="cstm-slidmenu-header" style="background-color: #dd3366">XXXXXXXXXX</span>';
      var contents3  = '<table width=180 border=0 cellspacing=0 cellpadding=0 bgcolor="#303040" ' +
                       'onMouseOver="cellbgcolor(¥'' + "#805080" + '¥');" ' +
                       'onMouseOut="bgrecover(¥'' + "#303040" + '¥')">';
          for (var i = 0; i < SlideMenu_ma.length; i++) {
              var smenuDef = SlideMenu_ma[i];
              var text = smenuDef.title;
              contents3 += '<tr><td width=15 align="right"><img src=' + smenuDef.img + '></td>' +
                           '<td width=165 height=20 align="left" class="menustr" onClick="JumpURL(¥'' + smenuDef.url+ '¥')">' + text + '</td></tr>';
          }
          contents3 += '</table>';
 
        // ***** SlideMenu Option *****
        var options = {
            width:  '200px',
            height: '230px'
        }
        L.control.slideMenu(header1+contents1+contents2+header3+contents3, options).addTo(map);
 
      //***** 画像を右下に追加 *****
      var img = L.control({position: 'bottomright'});
          img .onAdd = function (map) {
          this._div = L.DomUtil.create('div', 'imglinfo');
          this.update();
          return this._div;
      };
          img.update = function () {
          this._div.innerHTML = '<img src="./image/fugaku36.png" width=190 height=150>'
      };
      img.addTo(map);
 
      //***** スケールの表示 *****
      L.control.scale({imperial:false}).addTo(map);
 
      //***** マーカー全体が入るボックスを作る *****
      var bound = L.latLngBounds(markerList[0].pos, markerList[0].pos);
 
      //***** markerListの設定でマーカーを展開 *****
      for (var num in markerList) {
           var mk = markerList[num];
           var popup = L.popup().setContent(mk.name);
 
           //***** ツールチップ付加で地域ブロック毎にアイコン色分け表示 *****
           var mIcon = L.icon({
               iconUrl: mk.iconUrl,
               iconSize: mk.iconSize
           });
           markers[num]=L.marker(mk.pos,{ icon:mIcon }).bindPopup(popup).bindTooltip(mk.title).addTo(map);
 
    &#12288;     //***** マーカー全体が入るボックスを広げる *****
           bound.extend(mk.pos);
      }
  }
 
     //***** コンボボックスの浮世絵名を選択するとポップアップ *****
     function selText(obj){
         var idx = obj.selectedIndex;
         var value = obj.options[idx].value;
         markers[value].openPopup();
     }
</script>
</head>
<body onload="init()">
  <div id="mapcontainer" style="position:absolute;top:0;left:0;right:0;bottom:0;"></div>
</body>
</html>

fugakudef.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
//***** 浮世絵名配列 *****
 var selbox= [
     { val:"",name:"浮世絵名"},{val:"0",name:"01.磯川雪ノ旦"},{val:"1",name:"02.遠江山中"},{val:"2",name:"03.尾州不二見原"},
     { val:"3",name:"04.五百らりん寺さざねどう"},{val:"4",name:"05.御厩川岸より両国橋夕陽見"},{val:"5",name:"06.江戸日本橋"},{val:"6",name:"07.甲州三嶌越"},
     { val:"7",name:"08.甲州三坂水面"},{val:"8",name:"09.甲列伊沢曙"},{val:"9",name:"10.山下白雨"},{val:"10",name:"11.従千住花街御眺望ノ不二"},
     { val:"11",name:"12.駿州江尻"},{val:"12",name:"13.駿州大野新田"},{val:"13",name:"14.諸人登山"},{val:"14",name:"15.常州牛堀"},
     { val:"15",name:"16.信州諏訪湖"},{val:"16",name:"17.深川万年橋下"},{val:"17",name:"18.穏田の水車"},{val:"18",name:"19.青山円座松"},
     { val:"19",name:"20.東都浅草本願寺"},{val:"20",name:"21.相州梅沢左"},{val:"21",name:"22.相列仲原"},{val:"22",name:"23.登戸浦"},
     { val:"23",name:"24.東海道吉田"},{val:"24",name:"25.東海道金谷ノ不二"},{val:"25",name:"26.東海道程ヶ谷"},{val:"26",name:"27.東海道品川御殿山ノ不二"},
     { val:"27",name:"28.東都駿台"},{val:"28",name:"29.武州千住"},{val:"29",name:"30.隅田川関屋の里"},{val:"30",name:"31.本所立川"},
     { val:"31",name:"32.凱風快晴"},{val:"32",name:"33.神奈川沖浪裏"},{val:"33",name:"34.武州玉川"},{val:"34",name:"35.甲州犬目峠"},
     { val:"35",name:"36.武陽佃嶌"},{val:"36",name:"37.甲州石班沢"},{val:"37",name:"38.下目黒"},{val:"38",name:"39.上総ノ海路"},
     { val:"39",name:"40.相州江の島"},{val:"40",name:"41.東海道江尻田子の浦略図"},{val:"41",name:"42.相州箱根湖水"},{val:"42",name:"43.駿州片倉茶園ノ不二"},
     { val:"43",name:"44.相州七里濱"},{val:"44",name:"45.身延川裏不二"},{val:"45",name:"46.江都駿河町三井見世略図"}
 ];
 
//***** 簡易マイ・メニュー定義( SlideMenu) *****
var SlideMenu_ma = [
     { title: 'XXXXXXXXXXX', url: 'XXXXXXXXXXXXXXXX',img: '"./image/ball3.png" width=8 height=8 align="absmiddle"' },
     { title: 'XXXXXXXXXXX', url: 'XXXXXXXXXXXXXXXX',img: '"./image/ball3.png" width=8 height=8 align="absmiddle"' },
     { title: 'XXXXXXXXXXX', url: 'XXXXXXXXXXXXXXXX',img: '"./image/ball3.png" width=8 height=8 align="absmiddle"' }
 ];
 
  // ****** 背景色変更 ******
  var obj,evobj;
  function bgrecover(bg) { evobj.style.backgroundColor=bg; }
  function setColor(obj,col) { obj.style.backgroundColor = col; }
 
  // ****** 'table' , 'tr'タグ部分を避ける制御  *****
  function cellbgcolor(bg) {
      evobj=event.srcElement;
      if(evobj.tagName=="TABLE") {
         return
      }
      while(evobj.tagName!="TR") {
            evobj=evobj.parentElement;
      }
      evobj.style.backgroundColor=bg;
  }
 
  // ****** 別のHTMLに切替 (target="_blank") ******
  function JumpURL(URL) {
      window.open(URL,'_blank',"directories=no,location=yes,menubar=yes,resizable=yes,scrollbars=yes,status=yes,toolbar=yes");
  }
fugaku.css
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
a          { font-size: 12px;text-decoration:none;font-family:Meiryo UI; }
a:link     { color:#0033aa; }
a:hover    { color:#aa0000; }
a:visited  { color:#0000ff; }
body       { font-size: 12px;font-family:Meiryo;
            margin0;
            padding: 0;
}
.info {
            padding: 10px 10.5px;
            background: white;
            border-radius: 3px;
}
.legend-item {
            display: flex;
            font-family : Meiryo UI;
            font-size: 10.5px;
            color: #555555;
            width: 165px;
            align-items: center;
}
.legend-item-color {
            display: block;
            width: 15px;
            height: 15px;
            margin-right: 5px;
}
.cstm-slidmenu-header {
            display: block;
            margin: 0;
            font-size: 14px;
            font-weight: bold;
            width: 180px;
            color: #ffffff;
            text-align : center;
}
.menustr {
            font-size: 11px;
            font-family: Meiryo UI;
            padding-left: 6px;
            color: #ffffff;
            cursor: pointer;
}
.combinfo-set {
            font-size: 11px;
            font-family:Meiryo;
            color: #000000;
            width: 180px;
            height: 20px;
            margin-top: 1px;
            margin-bottom: 1px;
            background: #fefcc8;
            cursor: pointer;
}

2-1.アイコンマーカーの配置とポップアップ

マーカーの配置やポップアップのコード部分は、「気象庁震度観測点マップ」と同じです。コードの説明は「気象庁震度観測点マップ」を参照して下さい。 大量のアイコンマーカーの配置とポップアップ(吹き出し)を指定した座標(緯度、経度)の位置に展開します。 種類の違う複数の任意アイコン画像のマーカーを指定した位置に配置するために外部ファイルとしてfugaku.jsとして作成します。 fugaku.jsも「気象庁震度観測点マップ」の構成と相違ありません。データ内容が違うだけです。

※リスト表示にsyntaxhighlighterを利用していますが、スクリプト中に<br>タグを含んでいる 箇所が何箇所かあり、fugaku.jsコード表示が正しく表示されないため掲載していません。コードは一部分のみのサンプルですが、下記から確認して下さい。

fugaku.jsファイル確認


3.ソースコードについて

掲載しているソースコードのライセンスは、CC0 (クレジット表示不要、改変可、商用可) とします。自由に利用して頂いてかまいません。 作品で利用しているアイコンマーカー画像ファイル等は提供していませんので、お手数ですが各自で準備して下さい。尚、ソースコードは予告なく修正を加えて 更新することがあります。予めご了承願います。また、ブラウザのソースコード表示などで表示して確認やコピー、URLから直接ダウンロードするなども自由に行ってもかまいません。 全て自己責任でお願いします。

■関連記事
・Leafletで地図を作ろう - (イントロダクション)
・Leafletで地図を作ろう - (気象庁震度観測点マップ)
・Leafletで地図を作ろう - (都道府県別人口統計マップ)
・Leafletで地図を作ろう - (東海道五十三次ルートマップ)
・Leafletで地図を作ろう - (四国遍路巡礼マップ)

コメント

このブログの人気の投稿

Excelアドインで日本語形態素解析

階層構造JSONファイルの作成

キーボードのキーコードの一覧表