HSPでleafletを使って地図を作る(サンプル)

1.概要

地図については、Leafletで地図を作ろう - (気象庁震度観測点マップ)でJavaScriptで作成したものを 紹介していますが、今回は、このLeaflet地図をHSP言語に一部移植して見ました。JavaScript版では、外部ファイル化した定義コードやライブラリもあり、それらをHSPコード内に記述するのも めんどうだったので、サンプルということで簡易版として再現して見ました。

2.ソースコード

ソースコードは下記の通りです。HSPからHTMLコードなどを記述して生成後、起動させる方法として 良く利用される手法を使っています。具体的なコードとしては、193~197行目となります。
マーカーやポップアップの定義部分をデータベースのテーブルとして持ち、読み出して他のコードと同様に バッファに格納して一時ファイルとして保存後、ie->"Navigate"で起動させています。 該当部分は、115行~136行目の部分です。他の部分としては、ウィンドウ制御として起動時の最大化処理と リサイズ処理をWindows APIを利用して処理しています。 地図としてメインとなるHTML(Javascript)は、Leafletで地図を作ろう - (気象庁震度観測点マップ)を 参照願います。
eqmpoint.hsp
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
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
  ;****************************************************************************************
  ;*
  ;*    気象庁震度観測点マップ (eqmpoint) Ver1.0
  ;*
  ;*    <処理の概要>
  ;*    本プログラムは、象庁震度観測点一覧表の住所から緯度・経度を調査して
  ;*    整理したものから、leafletを利用してマッピングしたものである。
  ;*
  ;*
  ;*    出典: 気象庁震度観測点一覧表
  ;*           URL  https://www.data.jma.go.jp/svd/eqev/data/kyoshin/jma-shindo.html
  ;*           地図 : leaflet (オープンソースJavascript ライブラリ)
  ;*           地図タイル : 国土地理院タイル、オープンストリートマップ
  ;*           URL  https://maps.gsi.go.jp/development/ichiran.html
  ;*
  ;*
  ;****************************************************************************************
 
  #include "sqlele.hsp"
 
  #packopt type 0
  #packopt name "eqmpoint"
  #packopt runtime "hsprt"
  #packopt manifest "app.manifest"
  #packopt icon "SetDisp.Ico"
  #packopt hide 1
   
  #uselib "user32.dll"
  #func   SetWindowLong "SetWindowLongA" int,int,int
  #func   GetWindowLong "GetWindowLongA" int,int
  #func   InvalidateRect "InvalidateRect" int,int,int
  #func   MoveWindow "MoveWindow" sptr,sptr,sptr,sptr,sptr,sptr
  #func   DestroyWindow "DestroyWindow" int
  #func   GetWindowRect "GetWindowRect" int,var
 
  #define DIID_DWebBrowserEvents2     "{34A715A0-6587-11D0-924A-0020AFC7AC4D}"
  #define DISPID_NAVIGATECOMPLETE2    252
  #define TEMP_FILE dir_cur+"/exec.tmp"
  #define WS_MAXIMIZEBOX  0x00010000
  #define WS_SIZEBOX      0x00040000
  #define WM_SYSCOMMAND $00000112
  #define WM_COMMAND    $00000111
  #define WM_SIZE     $00000005
  #define SC_MAXIMIZE   $0000F030
 
  #module
  #uselib "kernel32.dll"
  #cfunc  CreateMutex "CreateMutexA" int,int,sptr
  #cfunc  GetLastError "GetLastError"
 
  ;***** 二重起動防止 *****
  #deffunc wexapend str prm1
  strname=prm1
  ;***** 名前の文字列が省略された場合 *****
  if strlen(strname)==0 : strname="HSP340ONIWND"  ;Default String
  ret=CreateMutex(0,1,strname)
  ;二重起動か?
  if GetLastError()==0    : return 0  ;同じジョブが起動していない
  if GetLastError()==183  : return 1  ;既に起動している
  return -1
  #global
 
  ;***** 起動ディレクトリ取得 *****
  sdim Startdir,512
  if hspstat&1=0 { Startdir=dir_exe+"¥¥" : chdir dir_exe
  } else {
    Startdir=dir_cur+"¥¥"
  }
  chdir Startdir
 
  ;***** データベース存在確認 *****
  exist Startdir+"setting¥¥eqmpoint.ini"
  if strsize ==-1 {
    dialog "データベースファイルが見つかりません。",0 : end
  }
  await
 
  wexapend "eqmpoint" : if stat : end
 
  ;***** データベースオープン *****
  sql_open Startdir+"setting¥¥eqmpoint.ini"
  onexit goto *owari
   
  screen 0,ginfo_dispx,ginfo_dispy,2,(ginfo_dispx-728)/2,(ginfo_dispy-600)/2,728,600
  GetWindowLong hwnd, -16
  SetWindowLong hwnd, -16, stat | WS_MAXIMIZEBOX | WS_SIZEBOX
  color 240,240,240 : boxf
  pos 0, 0 : axobj ie, "Shell.Explorer.2", ginfo_dispx+16, ginfo_dispy-26 : objIE=stat
   
  hwndIE=objinfo(objIE, 2)
  if objIE == -1 {
    dialog "ActiveXコントロールの配置に失敗しました。", 1
    end
  }
 
  ;***** HTMLタグ生成 *****
  sdim buff,10000 : sdim UPD_INFO,128,7
   
  buff = "<!DOCTYPE html>¥n"
  buff+= "<html>¥n"
  buff+= "<head>¥n"
  buff+= "  <meta charset=¥"shift-jis¥">¥n"
  buff+= "  <title>気象庁震度観測点マップ</title>¥n"
  buff+= " <link rel=¥"stylesheet¥" href=¥"https://unpkg.com/leaflet@1.3.0/dist/leaflet.css¥" />¥n"
  buff+= "  <script src=¥"https://unpkg.com/leaflet@1.3.0/dist/leaflet.js¥"></script>¥n"
  buff+= "  <style>¥n"
  buff+= "        a        { font-size: 12px;text-decoration:none;color:#0000aa;font-family:Meiryo; }¥n"
  buff+= "        a:link   { font-size: 12px;text-decoration:none;color:#0000aa;font-family:Meiryo; }¥n"
  buff+= "        a:hover  { font-size: 12px;text-decoration:none;color:#aa0000;font-family:Meiryo; }¥n"
  buff+= "        body     { ont-size: 12px;font-family:Meiryo; }¥n"
  buff+= "  </style>¥n"
  buff+= "  <script>¥n"
  buff+= "    //***** マーカーに表示したい対象の緯度経度とポップアップする名称を設定 *****¥n"
  buff+= "    var gmapstr = ¥"https://maps.google.co.jp/maps?q=¥";¥n"
  buff+= "    var markerList = [
 
  sql_q "SELECT * FROM eqmaptbl"
  count = stat
  repeat count,1
    UPD_INFO(1)  = sql_v("Tcode")
    UPD_INFO(2)  = sql_v("Tfuken")
    UPD_INFO(3)  = sql_v("ChikiName")
    UPD_INFO(4)  = sql_v("MoniPoint")
    UPD_INFO(5)  = sql_v("MoniAdd")
    UPD_INFO(6)  = sql_v("Ido")
    UPD_INFO(7)  = sql_v("Keido")
 
    buff+= "      { pos: ["+UPD_INFO(6)+","+UPD_INFO(7)+"], name: ¥""+UPD_INFO(4)+"
<a href=¥'¥"+gmapstr+"
    buff+= "¥""+UPD_INFO(6)+","+UPD_INFO(7)+"¥' target=¥'_blank¥'>"+UPD_INFO(5)+"</a>¥" },¥n"
 
    sql_next
  loop
  sql_close
   
  buff+= "    ];¥n"
  buff+= "    function init(){¥n"
  buff+= "      var map = L.map(¥'mapcontainer¥');¥n"
  buff+= "      //***** 座標の指定 *****¥n"
  buff+= "      var mpoint = [38.757436, 140.312227];¥n"
  buff+= "      map.setView(mpoint, 6);¥n"
  buff+= "      //***** 3つの地図タイルを切り替える *****¥n"
  buff+= "      var gsi =L.tileLayer(¥'https://cyberjapandata.gsi.go.jp/xyz/std/{z}/{x}/{y}.png¥',¥n"
  buff+= "        {attribution: ¥"<a href=¥'https://maps.gsi.go.jp/development/ichiran.html¥' target=¥'_blank¥'>地理院タイル</a>¥"});¥n"
  buff+= "      var gsipale = L.tileLayer(¥'http://cyberjapandata.gsi.go.jp/xyz/pale/{z}/{x}/{y}.png¥',¥n"
  buff+= "        {attribution: ¥"<a href=¥'http://portal.cyberjapan.jp/help/termsofuse.html¥' target=¥'_blank¥'>地理院タイル</a>¥"});¥n"
  buff+= "      var osm = L.tileLayer(¥'http://tile.openstreetmap.jp/{z}/{x}/{y}.png¥',¥n"
  buff+= "        {  attribution: ¥"<a href=¥'http://osm.org/copyright¥' target=¥'_blank¥'>OpenStreetMap</a> contributors¥" });¥n"
  buff+= "      //baseMapsオブジェクトのプロパティに3つのタイルを設定¥n"
  buff+= "      var baseMaps = {¥n"
  buff+= "        ¥"地理院地図¥" : gsi,¥n"
  buff+= "        ¥"淡色地図¥" : gsipale,¥n"
  buff+= "        ¥"オープンストリートマップ¥"  : osm¥n"
  buff+= "      };¥n"
  buff+= "      L.control.layers(baseMaps).addTo(map);¥n"
  buff+= "      gsi.addTo(map);¥n"
  buff+= "      //***** 画像マーカを設定 *****¥n"
  buff+= "      var markerIcon = L.icon({¥n"
  buff+= "           iconUrl: './image/ball.png',¥n"
  buff+= "           iconRetinaUrl: './image/ball.png',¥n"
  buff+= "           iconSize: [18,18],¥n"
  buff+= "           iconAnchor: [8,8],
  buff+= "           popupAnchor: [0,-16]¥n"
  buff+= "      });¥n"
  buff+= "      //***** マーカー全体が入るボックスを作る *****¥n"
  buff+= "      var bound = L.latLngBounds(markerList[0].pos, markerList[0].pos);¥n"
  buff+= "      //***** markerListの設定でマーカーを追加 *****¥n"
  buff+= "      for (var num in markerList) {¥n"
  buff+= "        var mk = markerList[num];¥n"
  buff+= "        var popup = L.popup().setContent(mk.name);¥n"
   
  ;***** マーカ画像がない場合は、標準マーカを使用 *****
  exist Startdir+"image¥¥ball.png"
  if strsize ==-1 {
    buff+= "        //●標準マーカ (使用しない)¥n"
    buff+= "        L.marker(mk.pos).bindPopup(popup).addTo(map);¥n"
  }else{
    buff+= "        //●画像マーカ¥n"
    buff+= "        L.marker(mk.pos,{ icon:markerIcon }).bindPopup(popup).addTo(map);¥n"
  }
   
  buff+= "        //***** マーカー全体が入るボックスを広げる *****¥n"
  buff+= "        bound.extend(mk.pos);¥n"
  buff+= "      }¥n"
  buff+= "    }¥n"
  buff+= "  </script>¥n"
  buff+= "</head>¥n"
  buff+= "<body onload=¥"init()¥">¥n"
  buff+= "  <div id=¥"mapcontainer¥" style=¥"position:absolute;top:0;left:0;right:0;bottom:0;¥"></div>¥n"
  buff+= "</body>¥n"
  buff+= "</html>¥n"
 
  ;***** 一時ファイルとしてセーブ *****
  bsave TEMP_FILE, buff, strlen(buff)
  ;***** HTMLファイルを起動 *****
  ie->"Navigate" "file:///"+TEMP_FILE
  comevent ie_event, ie, DIID_DWebBrowserEvents2, *event
 
  ;***** ウィンドウを最大化 *****
  oncmd gosub *GUIResize,WM_SIZE
  sendmsg hwnd,WM_SYSCOMMAND,SC_MAXIMIZE,0
  gsel 0,1
  stop
 
*GUIResize
  ;***** リサイズ処理 *****
  gsel 0,1
  InvalidateRect hwndIE,0,1
  MoveWindow hwndIE, 0, 0, ginfo_winx+16, ginfo_winy-26, 1
  color 240,240,240 : boxf
  color 200,200,200
  line 0,ginfo_winy-26,ginfo_winx+16, ginfo_winy-26
  font "Meiryo UI",11,0 : color 20,20,20
  pos 10,ginfo_winy-20 : mes "出典:国土地理院 - 地理院地図、淡色地図 | OpenStreetMap - contributors"
  return
 
*event
  dispid = comevdisp(ie_event)
  if dispid = DISPID_NAVIGATECOMPLETE2 : title "気象庁震度観測点マップ"
  return
 
 
*owari
  ;***** 終了処理 *****
  gsel 0,0
  await
  ;***** 一時ファイルを削除 *****
  exist TEMP_FILE
  if strsize !=-1 {
    delete TEMP_FILE
  }
  delcom ie
  end

3.ダウンロード

提供するソースコードのライセンスは、CC0 (クレジット表示不要、改変可、商用可) とします。自由に利用して頂いてかまいません。 尚、データの取得やプログラム実行において損害等が生じた場合は、筆者は一切の責任も負いません。全て自己責任でお願いします。

実行形式(exe)ファイルとソースコード一式のアーカイブは下記よりダウンロードして下さい。

ダウンロード

■関連記事
・Leafletで地図を作ろう - (気象庁震度観測点マップ)

コメント

このブログの人気の投稿

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

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

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