震度分布図を作ろう① ～ブラウザ上に地図表示～

![20231208232429.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3637649/8aad7592-918d-4aff-ccfc-a9518eb7d89f.png)

:::note warn
この開発にはサーバーを使用します。
自分のPC上、ローカルでは一手間しないと動きません。
:::

## どうもみなさんこんにちは。

いきなりですが、震度分布図を公開してから約1年が過ぎました。[^1]
1年経つと[^2]、震度分布図の作り方を教えてほしいという声が結構来ますが、個人個人に全て教えていると時間がいくらあっても足りないので、記事にして公開してしまおうと思い、Qiitaを書き始めました。

私は記事というか長い文章を書いていると、絶対に話がそれるというか一本の筋をつかめていない？ので、わかりにくいところが~~あると思います~~ 確実にありますが、その場合は自分で調べてくださいね。コメントしてもらってもいいですが説明は下手です。

とにかく説明とか文章作成が下手です。何を言っているのか言いたいのか分からないところがたくさんあると思います。ご了承を。

## 環境整備
環境整備と言っても、Pythonのように何かをインストールしないと動かないというわけではないので、自身の使いやすい環境があるのならば飛ばしてもらっても構いません。

何個か書いておきますので好きなのを選んでください。
上からおすすめ順です。

### エディタ

#### ①VSCodeのインストール
まだJavaScriptをしたことがない人は、エディターとして、VSCodeをおすすめします。
なぜかというと、まあ使いやすいし、みんな使っていて情報がたっぷりあるからです。
ただ、インストール手順は私が言うよりもわかりやすそうなものがあるので拝借します。

https://webst8.com/blog/vscode-install/

#### ②VSCodeのWeb版
VSCodeはWeb、ブラウザ上でも使用できます。
インストールしたくないわ、できへんわの人におすすめ。

https://vscode.dev/

ただ、やはりアプリとWeb、そもそも目的が違います。
アプリはコンピューターを操作するもの、Webはちょろっと見るだけのものです。
ちょろっと見る用のWebに対するローカルへのアクセスはアプリと比べて大幅に制限されています。
覗いてみただけなのにファイルを消されたり、上書きされたら大変ですから。

よって、Web版は便利ですが、ファイルの取り扱い面に関してはやはり弱いです。
本当に保存されているか否か本当に不安になります。
#### ③気合のメモ帳
最後は、インストールしたくないわ、VSCode Webも使いたないわ、OS公式以外のアプリ嫌や、Windowsにもとから入ってんのんが一番安全やわ。の人におすすめ（そんなやつおらんやろ）

メモ帳です。そうあれ。
メモ帳でもちゃんと作れます。保存できます。
ただ、カスです。
メモ帳はメモをチョチョイと書き込み用のものであり、コードを書くものではありません。
気合で行く人はどうぞ。


### Live Serverを立ち上げる
はじめに

:::note warn
この開発にはサーバーを使用します。
自分のPC上、ローカルでは一手間しないと動きません。
:::

と書いたのはこのためです。
HTMLファイルをダブルクリックしたりブラウザにドラッグアンドドロップしたりして、アドレスバーに`C:/Users/`とかとなっている場合は、この開発では動かず動作を確認できません。

そのため、自分のパソコン内にサーバーを作ってアクセスします。
そのためのVS Code拡張機能がLive Serverというものです。
さきほどでVS Codeをインストールしたなら良いですが、Web版だったり気合だったりすると拡張機能が使えないのでやっぱり大人しくVS Codeをインストールしてください。

立ち上げ手順はこちらをご参照くださいませ。

https://qiita.com/nemu-a1021/items/dbfef56fdc38e0287ebc

<details><summary>Live Serverが必要な理由</summary>

どういうこと？？
`C:/Users/`でもLive Serverでも自分のパソコンの中なんだから一緒なんじゃないの？？
となっている人。すばらしいです。たぶんこういうの向いてると思いますよ。

さて理由をお話しましょう。
理由はこの開発で使う、`fetch`や`$.getJSON`などの他所様（他のサーバー）からファイルを取得するコマンドが`C:/Users/`などのローカルファイルでは使えないからです。
なんで使えないのか？

そもそも、Webブラウザには「同一オリジンポリシー」というのがあり、「一緒のオリジン（ドメインexample.comとかと考えてOKです）しかアクセスを許しませんよ！」つまり「他のところにはアクセス禁止ですよ」ということを決めています。
そして、Live Serverなどで出てくる`http://localhost`や`http://127.0.0.0`みたいなところは「一緒のオリジン」として認識されます。
しかし、`file:///C:/Users/`ではいくら同じ`C:/Users`であっても同じオリジンとはみなされません。
これは、ローカルのファイルがとても重要（パソコンの中に個人情報とかのファイルが入っているとか）であるからであるのと、そもそも`file:///`というプロトコルそのものが`https://`とかとは違うので違うオリジンとみなされるのです。
`http://localhost`や`http://127.0.0.0`みたいなところはこのように一手間しないといけないですから、何もしなくてもファイルが有る`file:///C:/Users/`と比べて制限が特別緩くなっています。

よって、これらのことからLive Serverを立ち上げないと、この開発で使うよそからファイルを取ってくることができなくなってしまうため、Live ServerもしくはWebサーバーが必要となります。

</details>

### 無料サーバー
先程の手順でLive Serverを立ち上げた人とサーバーはすでに持っている人は飛ばしてくださいね。
#### ①[シン・クラウド for Free](https://www.xfree.ne.jp/)
私もこれ使ってます。最高です。
無料で10GBも使えて広告なしでSSLまで対応ってどういうことですか！？
XFREEさん無料で大丈夫？？

:::note info
容量：<b>10GB SSD</b>　広告表示：<b>なし</b>
SSL：<b>無料あり</b>　DB：<b>無料あり</b>
（情報は 2024/07/14時点）
:::

#### ②[スターサーバーフリー](https://www.star.ne.jp/free/)
XFREEに乗り換える前まで使っていました。

:::note info
容量：2GB or 4GB　広告表示：なし(4GBはあり)
SSL：なし　DB：なし
（情報は 2024/07/14時点）
:::

#### ③[XREA Free](https://www.xrea.com/)
一回だけ使ったことがありましたが、転送量制限があったのでやめました。

:::note info
容量：<b>10GB</b>　広告表示：あり
SSL：<b>無料あり</b>　DB：<b>無料あり</b>
（情報は 2024/07/14時点）
:::

:::note alert
転送量制限[^3]が<b>「5GB / 日」</b>と設定されているので、地図などの重いデータを使っていると、アクセス増のときにワンチャン見れなくなる可能性があります。
:::

## 開発スタート
### HTMLファイルを作る
HTMLファイルがないと始まりません。
下の折りたたみが基礎のHTMLとCSSファイルです。

<details><summary>ソースコード</summary>

```diff_html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <title>震度分布図</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="index.css">
</head>
<body>
    
</body>
</html>
```
```diff_css:index.css
html, body {
    width: 100%;
    height: 100%;
    margin: 0;
}
```

</details>

さて、これをコピーして保存してください。

### Leafletを読み込む(HTML側)
ブラウザで地図を表示するのはとても難しいです。
触ったら動かす、表示する地図を読み込む、ズームする…。
ただ、これは全て自分でやろうとするときはとても難しいですが、世界は広いです。
<INS>**自分がしなくたって誰かが代わりにきっとやってくれてます。**</INS>
そしてありがたいことに、ブラウザに地図を表示する、という開発は誰かがすでにしてくれています。
その一つが「Leaflet」という訳です。

さて、すでに何を書いているのかわかりませんが、開発に取り掛かっていきましょう。
ここに書いてあるJSとCSSのscript、linkタグをパクってきます。
また、Leafletでは、`<div id="map"></div>`中に地図が表示されるようになっています[^4]ので、それも追加しておきましょう。

また、のちのちjQuery（JavaScriptのライブラリ。実装したい機能をサッと書くことができて便利なやつ。読み込んどいて損なし。）も使うので、読み込みます。

https://leafletjs.com/download.html

<details><summary>ソースコード</summary>

```diff_html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <title>震度分布図</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="index.css">
+   <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="" />
+   <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
+   <script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
</head>
<body>
+   <div id="map"></div>
</body>
</html>
```
```diff_css:index.css
+ html, body, #map {
    width: 100%;
    height: 100%;
    margin: 0;
}
```

</details>

これでHTML側での地図の表示の準備は整いました。

### Leafletを使用して地図を描画する(JS側)
続いて、JavaScriptで何を表示するか設定していきましょう。
とりあえず[公式ページ](https://leafletjs.com/index.html)に乗っていて安心できそうなものをやってみましょう。
ここでJavaScriptファイル、index.jsを作ります。HTMLの中にぶち込んでもおｋです。

<details><summary>ソースコード</summary>

```diff_html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <title>震度分布図</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="index.css">
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="" />
    <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
    <script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
</head>
<body>
    <div id="map"></div>
+    <script src="index.js"></script>
</body>
</html>
```
```diff_javascript:index.js
+ var map = L.map('map').setView([51.505, -0.09], 13);
+ 
+ L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
+     attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
+ }).addTo(map);
+ 
+ L.marker([51.5, -0.09]).addTo(map)
+     .bindPopup('A pretty CSS popup.<br> Easily customizable.')
+     .openPopup();
```

オマケ：[なんでindex.jsはLeafletみたいにheadの中に書かないの？](https://qiita.com/kottaro123456/items/80bd3532c5db1f78a880#%E3%82%AA%E3%83%9E%E3%82%B1)

</details>

一回`index.html`を開いてみましょう。
たぶんどこかしらの地図が表示されているはずです。
されなかったらF12で開発者ツール＞コンソールを開いて、エラー源を特定しましょう。
エラーの文をそのままGoogleにぶち込めば何かしら解決策が出てくるはずです。

![1000020601.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3637649/904dc792-83dc-d732-b131-a96664145cce.png)


## 最後に
これで地図は表示できるようになりました。
一つの記事でこれ以上書き連ねてしまうと、行き先がわからなくなってしまうので今回はこんな感じで。

今回のデモ
https://nanka.cloudfree.jp/bin/webapps/shindobunpu_qiita/1/

<details><summary>今回までのソースコード</summary>

```diff_html:index.html
<!DOCTYPE html>
<html lang="ja">
<head>
    <title>震度分布図</title>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="index.css">
    <link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" integrity="sha256-p4NxAoJBhIIN+hmNHrzRCf9tD/miZyoHS5obTRR9BMY=" crossorigin="" />
    <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
    <script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
</head>
<body>
    <div id="map"></div>
    <script src="index.js"></script>
</body>
</html>
```
```diff_javascript:index.js
var map = L.map('map').setView([51.505, -0.09], 13);

L.tileLayer('https://tile.openstreetmap.org/{z}/{x}/{y}.png', {
    attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
}).addTo(map);

L.marker([51.5, -0.09]).addTo(map)
    .bindPopup('A pretty CSS popup.<br> Easily customizable.')
    .openPopup();
```
```diff_css:index.css
html, body, #map {
    width: 100%;
    height: 100%;
    margin: 0;
}
```

</details>

## 次回予告
震度分布図を作ろう② ～シンプルな地図にしよう～

https://qiita.com/kottaro123456/items/2d3f96262ff168bbc769

## オマケ
### なんでindex.jsはLeafletのようにheadの中に書かないの？
たしかにそうですね。
```html:index.html
<head>
    …
    <script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js" integrity="sha256-20nQCchB9co0qIjJZRGuk2/Z9VM+kNiyxNV1lvTlZBo=" crossorigin=""></script>
    <script src="https://code.jquery.com/jquery-3.7.1.min.js" integrity="sha256-/JqT3SQfawRcv/BIHPThkBvs0OEvtFFmqPF/lYI/Cxo=" crossorigin="anonymous"></script>
</head>
<body>
    <div id="map"></div>
    <script src="index.js"></script>
</body>

```
`index.js`のみ`</body>`の直前で書かれています。
確かにleafletやjQueryが`<head>`の中ならば、`index.js`も`<head>`の中でいいではないか。
と思いますが、これには深いわけがあります。

約2年前、私がJavaScriptを始めたとき。
最初は`<div>`の中を書き換えようとしたのか何なのか、`<head>`の中にJavaScriptを実行しようとしていました。
コードとしてはこんな感じです。
`document.getElementById('div').innerText = "変わったよん";`
**ただ、これが`<head>`の中にあれば、エラーが発生して実行されません。**

なぜでしょうか。

答えはHTMLにありました。
ブラウザはHTMLを理解しようと上から順番に読んでいきます。
そして、上から読んでいく中で`<script src="">`があれば、そのファイルも読み込んで、実行しようとします。
しかし、`<head>`の中にあれば、上から読んでいくので、まだ`<body>`は読み込まれていないことになります。
その`<body>`が読み込まれていない状態で「おーい、idがdivのやつをくれや」と言っても、ブラウザは「え？body読めてないからdivはまだないねんけど」と返してしまいます。

そこがエラーとなって、実行されないという経緯がありました。

よって、これを解決するには「HTMLが読み込まれたあと」つまり、`</body>`の直前だと全て読み込み終わっているので、呼び出してもエラーとなりません。

だから私はindex.jsなどのHTML要素を呼び出す可能性があるものは、`</body>`の直前に書いているのです。

[^1]: 多分、絶対、確定で違います。確認もしてない、マジで適当です。
[^2]: もう一回言いますが違います。くそほど適当です。
[^4]: 嘘です。JavaScriptの`var map = L.map('map')`(3番目の'map')で変えられます。ただそういう慣習です。たぶん。
[^3]: どれだけのデータをクライアント(スマホやパソコンのブラウザ)に送れるかです。スマホのモバイルデータの残りギガ数とかと同じ仕組みです。