5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

MapLibreAdvent Calendar 2024

Day 14

MIERUNE/svelte-maplibre-glでWebメルカトルのゆがみを見る

Last updated at Posted at 2024-12-13

これは 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/

測量士でもなければ、地理学を学んだことのない私には、とてつもなく難しい話なのですが『経線を横にしたら緯線!』という単純なものではないようです。

  • 緯線は大小様々なドーナツ🍩が地球の表面に乗っかっている(😇)線
  • 経線は地球を(角度を変えながら)真っ二つにした線で、スイカ🍉を切るような線
    と理解することにしました。

image.png

ちなみに、下記の本で緯度と経度の違いに興味を持つことができました。

ハマったこと

  • MapLibre GL JSには、LineString描画する方法がない?!
    • LeafletL.polylineのようにLineStringを描画するものがない(?)
    • GeoJSONを作ってそれを描画する必要がありそう
  • SvelteKitScriptに書いたTypeScriptが実行されない?!
  • 画面が真っ白

実装のポイント

等間隔で緯度経度の線を描画して、高緯度では距離や面積が誇張されていることを確認してみようと思います。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>
5
2
1

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
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?