これは MapLibre Advent Calendar 2024 の14日目の記事です。
概要
GoogleMapで使われるWebメルカトルが『メルカトル図法』というものとは別物だ、ということを伊達と酔狂
で知られるWINGFIELD先生の本で知りました。
思いついてから夜なべして書きましたが、全部終わってから同じアドベントカレンダーでテーマが似ている記事があることに気づきました🫢この記事は私のポエム + MIERUNE/svelte-maplibre-glでできています。
普段の仕事では、パワポばかり書いている私ですが、
-
SvelteKit
の入門 -
Github Actions
&Github Pages
の入門 - TypeScriptの入門
-
MIERUNE/svelte-maplibre-glの入門
などを兼ねてSvelteKit
で人生初のポートフォリオなるものを作成してみます!
作ったもの
SevlteKitでインパクトのあるものとは?が想像できず、
下記を読んで「これ使えば簡単なのでは?」と思い挑戦しました。
作ったものは下記になります。
デモサイト:👉https://shinyanakashima.github.io/santa-magical-map/
よもやま話
楕円体である地図を地図に描く(投影)ときは、どうしても歪みが出てしまう。例えば、AとBでは同じように「10度」分の距離がありますがBの方が長く見えます。※CとDは「10度」分の距離がありますが、同じに見えます。
- 経線(南北)では緯度が変わると、長さが長くなっているように「描かれる」
- 緯線(東西)では経度が変わっても、同じような長さに「描かれる」
下記サイトでは、投影法の種類によって、どのような歪みが出るのかをわかり易く見ることができます。
https://www.wingfield.gr.jp/demos/map-projections/
測量士でもなければ、地理学を学んだことのない私には、とてつもなく難しい話なのですが『経線を横にしたら緯線!』という単純なものではないようです。
- 緯線は大小様々なドーナツ🍩が地球の表面に乗っかっている(😇)線
- 経線は地球を(角度を変えながら)真っ二つにした線で、スイカ🍉を切るような線
と理解することにしました。
ちなみに、下記の本で緯度と経度の違いに興味を持つことができました。
ハマったこと
-
MapLibre GL JS
には、LineString描画する方法がない?!-
Leaflet
のL.polylineのようにLineStringを描画するものがない(?) - GeoJSONを作ってそれを描画する必要がありそう
-
-
SvelteKit
でScript
に書いたTypeScript
が実行されない?!-
JavaScript
では<script>
を、TypeScriptでは<script lang="ts">
- https://svelte.jp/docs/typescript#script-lang-ts
-
- 画面が真っ白
- 理由はTailwindCSSを入れないと地図にCSSが当たらないず表示されなかったのです
実装のポイント
等間隔で緯度経度の線を描画して、高緯度では距離や面積が誇張されていることを確認してみようと思います。LineStringでのマウスホバー時のイベントハンドラや、GeoJSONを動的に生成するサンプルが見つからなかったのでMIERUNE/svelte-maplibre-glのソースを読みながら実装しました。
緯度経度のLineStringの生成
緯度経度のLineStringを作成するにあたり、Pythonのrange
関数がほしくなりましたが、TypeScript(JavaScript)では無さそうでした。それで下記のような関数を作りました。
const range = (min: number, max: number, step = 1) => {
return [...Array(Math.floor((max - min) / step) + 1).keys()].map((i) => min + i * step);
};
使い方としては、下記のように指定した範囲でLineStringを生成します。
今回、TypeScript初挑戦でしたので型がこれで良かったのか疑問です。
// 南緯80度~北緯80度までを、10度刻みで生成
const lines_lat = range(-80, 80, 10).map((_lat) => {
const featureLine: Feature<LineString, GeoJsonProperties> = {
type: "Feature",
properties: {},
geometry: {
coordinates: [
[-MAX_LNG, _lat],
[MAX_LNG, _lat],
],
type: "LineString",
},
};
return featureLine;
});
サンタの吹き出しの変更
日本の範囲を適当に決めて🎅のマーカーの吹き出しが変わるようにしました。判定はMaplibre GL JS
を使いました。
<Marker bind:lnglat draggable>
{#snippet content()}
<div class="text-center leading-none">
<div class="text-3xl">🎅🏽</div>
<div class="font-bold text-white drop-shadow-sm">{lngLatText}</div>
</div>
{/snippet}
<Popup class="text-black" bind:open={popupOpen} offset={offsets}>
{#if BOUNDS_JAPAN.contains(lnglat)}
<span class="text-lg">メリークリスマス🎄</span>
{:else}
<span class="text-lg">日本が恋しいのぅ...</span>
{/if}
</Popup>
</Marker>