Googleマップの位置情報タイムライン(エクスポートJSON)を読み込み、訪れた都道府県・市区町村の制覇マップ・移動統計・滞在履歴を俯瞰できるデスクトップアプリ(Electron製)です。
Googleマップ純正のタイムラインが「1日単位の振り返り」であるのに対し、本アプリは累積データの俯瞰・可視化に特化しています。
Node.jsの知識がなくても使えます。Releasesページから最新版のPathBrowser Setup <version>.exeをダウンロードして実行してください。インストール時にデスクトップ・スタートメニューにショートカットが作成されます。
署名なしの実行ファイルのため、初回起動時にWindows SmartScreenの警告(「WindowsによってPCが保護されました」)が表示されることがあります。「詳細情報」→「実行」で起動できます。管理者権限は不要です(インストール先はユーザーごとのフォルダになります)。
ソースコードから直接動かしたい場合は、Node.jsが必要です(Electron 43系が動作するバージョン)。
npm install
npm start起動すると位置情報タイムラインのJSONファイルを選択するダイアログが表示されます。自分でエクスポートしたファイルを選択してください(エクスポート方法は下記)。
初回読み込み時は市区町村判定・クラスタリングの計算のため数秒かかることがありますが、結果はOS標準のアプリデータフォルダにファイルとしてキャッシュされ、同じファイルを次回以降開いたときは再計算されません(クラスタリングのしきい値を変更した場合も、一度使ったしきい値はキャッシュされます)。除外ゾーンの設定も同じくOS標準のアプリデータフォルダに保存され、どのファイルを開いても引き継がれます。
- スマートフォンのGoogleマップアプリ、またはGoogleタイムラインの設定画面から「データのエクスポート」を行います(Googleアカウントの設定 > ロケーション履歴 > タイムラインデータのエクスポート)。
- ダウンロードされたJSONファイル(数十MBになることがあります)をそのまま本アプリで開けます。事前の変換・分割は不要です。
写真連携機能では、Exif GPSタグ付きの写真、またはGoogleフォトのGoogle Takeoutエクスポートを読み込めます。Takeoutで「Googleフォト」のみを選択してエクスポートすると、Takeout/Google フォト/以下に写真本体と位置情報付きのJSONファイル(写真名.jpg.supplemental-metadata.jsonなど)がペアで出力されるので、そのフォルダを設定画面の「写真連携」から選択してください(実際の位置情報を含む個人データなので取り扱いにはご注意を。処理はローカル完結で外部送信はありません。JPEG/PNGに加えiPhone等のHEIC形式もサムネイルプレビューに対応しています)。
すべての解析・判定・クラスタリング処理はローカルで行われ、位置情報データが外部に送信されることはありません。例外として、プライバシーモードOFF時に滞在地点の詳細パネルを開くと、その地点の座標のみをNominatim(OpenStreetMapの逆ジオコーディングAPI)に送信し、町名・施設名を取得します(地図タイル画像の取得含め、これ以外の外部通信はありません)。
アプリ内には自宅・職場を「除外ゾーン」として登録できるプライバシー保護機能があります(詳細は下記「主な機能」参照)。初回データ読み込み後、ブラウズを始める前に除外ゾーンの設定画面に案内されます。画面共有や録画をしている場合は、位置情報が映り込まないようご注意ください。
- 制覇マップ: 都道府県境界(または市区町村境界、粒度切り替え可)を日本地図上に描画し、訪問済みのエリアを訪問回数に応じた濃淡で塗り分けます。クリックするとその県の滞在回数・最初/最後に訪れた日・合計/平均滞在時間・市区町村制覇率・市区町村ごとの滞在地点一覧が表示されます。都道府県クリック時のズームは、多摩地区・伊豆諸島などの離島を含む外接矩形ではなく**面積最大のポリゴン(本土部分)**に合わせて表示され、離島に訪問済みの地点がある場合は詳細パネルにジャンプリンクが表示されます。
- 粒度切り替え: 制覇マップは「都道府県 / 市区町村」をワンクリックで切り替えられます。市区町村モードでは全国約1,894市区町村を描画しますが、表示範囲内のみを描画する形でパフォーマンスを確保しています。
- 配色: 塗りつぶし(訪問回数の濃淡)は単一色相の青系グラデーション(未訪問は薄いグレー)、滞在地点のピンは白縁取りのオレンジと、色相をはっきり分けているためピンが背景に埋もれません。選択中の都道府県は塗りつぶし色を変えず境界線の強調(オレンジ・太線)で示し、ピンや経路が前面に出るタイミングでは塗りつぶしの不透明度を自動的に下げます。
- 地名表示: 滞在地点は座標ではなく市区町村名(例:「京都市左京区」)で表示されます。プライバシーモードOFF時は、県の詳細パネルの滞在地点ランキングにも「回数 — 詳細地名(市区町村名)」の形でNominatim(OpenStreetMap)の詳細地名(施設名・建物名・町名)が表示されます。取得は表示中の行から優先的に・1秒1件以下で順次行われ(画面外の行はスクロールして見えるまで取得しません)、一度取得した地名はクラスタ単位でキャッシュされ、地図上のピンのツールチップにも反映されます。逆ジオコーディングに渡す座標は、クラスタ内で最も出現回数が多いplaceId(無ければ最頻座標)を使うことで、GPSのブレによる誤った地名取得を減らしています。
- 近接地点のクラスタリング: GPSのブレによる同一地点の重複記録を、距離ベースのクラスタリングで1つの滞在地点にまとめます。しきい値(20〜200m、デフォルト50m)はヘッダーのスライダーで調整可能です。
- 除外ゾーン(プライバシーモードのON/OFFに関わらず常時適用): 設定画面の地図上で円を描き、「なかったことにする」エリアを登録できます。自宅・職場と推定される地点や、最も滞在回数が多い地点(自宅の可能性が高い)は登録の候補として提案されます。除外ゾーン内のデータは、ランキング・地図のピン・経路(境界でトリム)・訪問一覧から除外されますが、都道府県/市区町村の訪問判定や合計距離などの集計値には影響しません。ゾーンの位置自体は設定画面以外には表示されません。
- 経路マップ: 移動経路をLeaflet上にポリラインで描画し、移動手段(徒歩=緑、車・バス=青、電車=赤など)に応じて色分けします。期間フィルタと連動し、データ量の都合上、期間(年)を絞り込んだときのみ描画されます。除外ゾーンに入る経路はゾーン境界でトリムされます。
- 写真連携(任意機能): 位置情報付きの写真が入ったフォルダを設定画面から連携すると、撮影地点を制覇マップ・経路マップの両方にピンとして重ねて表示できます(近接するピンはクラスタ表示、クリックするとサムネイルプレビュー、さらにクリックで拡大表示)。位置情報はExifのGPSタグを優先し、無ければGoogleフォトのTakeoutエクスポートに含まれるJSONサイドカーの位置情報を使用します(取得方法は下記「写真データの準備」参照)。撮影日時は期間フィルタと、位置は除外ゾーン・プライバシーモードと連動します(プライバシーモードON時は写真レイヤー自体が無効化されます)。読み取りはすべてローカルで行われ、外部送信はありません。
- 撮影地点の推定(位置情報のない写真): Exif・Takeoutどちらにも位置情報がない写真は、撮影日時とタイムラインの移動履歴(滞在・移動記録)を突き合わせて撮影地点を推定します(撮影時刻がどこかの滞在中ならその地点を、そうでなければ前後2時間以内の最も近い移動記録の地点を採用。それでも近い記録が無い場合は推定されず非表示のまま)。推定した地点はダッシュ縁取りの半透明ピンで表示され、ポップアップにも「位置情報: 推定(記録との時間差: 約n分/時間)」という注記が付き、実測データ(Exif/Takeout)と混同しないようになっています。
- 年表(初訪問クロニクル): 都道府県(既定)・市区町村の初訪問日を時系列に並べて表示します。項目をクリックすると該当エリアの制覇マップにジャンプします。
- 移動統計: 総移動距離、移動手段別の距離・回数・合計時間・平均速度、月別移動距離の手段別積み上げグラフ、最長移動ランキング(始点・終点の市区町村名付き)、市区町村制覇率ランキング(クリックでその県の市区町村マップへジャンプ)、よく行く場所ランキング(回数順/合計滞在時間順の切り替え可)、曜日別平均距離・時間帯別移動回数・最も移動した日トップ5などの行動パターン統計を表示します。
- タイムラプス再生: 制覇マップ上で再生ボタンを押すと、データの開始月から終了月まで月単位で自動的に期間フィルタが進み、地図が塗られていく様子をアニメーション表示します(都道府県/市区町村どちらの粒度でも動作)。一時停止・リセットが可能です。
- PNGエクスポート: 現在表示中の制覇マップ(粒度・期間フィルタ・プライバシーモード・除外ゾーンの状態をそのまま反映)を、画面表示をそのままキャプチャする形でPNG画像として保存できます。地図タイルのOSMクレジット表記も自動的に画像内に含まれます。
- 期間フィルタ: 年・月で絞り込むと、マップと統計がその期間のデータで再計算されます。年を指定すると「その年に初めて訪れた県」も表示されます。
- ドリルダウン・ナビゲーション: 日本地図 → 県 → 滞在地点、とパンくずリスト・戻る/進むボタンで移動できます。
- プライバシー保護モード(デフォルトON):
- 地図のズームレベルを市区町村が判別できる程度までに制限(番地・建物レベルには拡大不可)
- 滞在地点のピンは市区町村の代表点に丸めて表示(詳細地名・座標は非表示)
- 自宅(HOME)・職場(WORK)周辺1km以内のデータをすべての表示・統計から除外
- よく行く場所ランキングは市区町村単位に丸めて表示
- 経路マップ自体を無効化(生活圏が最も露出する機能のため)
data/prefectures.geojsonはdataofjapan/land(japan.geojson、都道府県単位のポリゴン、パブリックドメイン相当のオープンデータ)から取得し、アプリで使用するプロパティ(都道府県コード・名称)のみを残してファイルサイズを削減したものです。
https://raw.githubusercontent.com/dataofjapan/land/master/japan.geojson
data/municipalities.geojsonはsmartnews-smri/japan-topography(元データ: 国土交通省 国土数値情報「行政区域」、簡素化0.1%版、全国1,894市区町村・行政区)から取得し、同様にプロパティを間引いたものです。政令指定都市の区も個別に区分されているため、「京都市左京区」のような区単位の地名が表示できます。
https://raw.githubusercontent.com/smartnews-smri/japan-topography/main/data/municipality/geojson/s0001/N03-21_210101.json
簡素化0.1%版は1市区町村あたり平均17.6頂点しかなく、境界の見た目が粗くなる直接の原因になっています。同じ提供元・同じ出典表示の簡素化1%版(s0010、全国版ファイルはなく都道府県ごとに47ファイル、かつプロパティが国土数値情報の生の列名N03_001/N03_003/N03_004/N03_007のまま)に差し替えることで精度を上げられます。scripts/fetch-municipality-boundaries.js(npm run fetch:boundaries)が47ファイルの取得・列名変換・飛び地のMultiPolygon統合をまとめて行うので、通常のインターネット接続がある環境で一度実行すれば十分です。データそのものではなくスクリプトとして同梱しているのは、47ファイルの一括取得は実行環境によって不安定になりやすく、取得結果を都度確認しながら反映する方が安全なためです。
- Electron(メインプロセス: Node.js / レンダラー: 素のHTML・CSS・JS、UIフレームワークなし)
- 地図描画: Leaflet + OpenStreetMapタイル
- 都道府県・市区町村判定:
@turf/boolean-point-in-polygon(メイン/Worker側)、および除外ゾーン・HOME/WORK提案のための簡易Point-in-Polygon判定(レンダラー側、mapView.mjs) - 制覇マップのPNGエクスポート: Electronの
webContents.capturePage()で画面表示をそのままキャプチャ(追加ライブラリなし。表示中の内容をそのまま撮る方式のため、プライバシーモードや除外ゾーンの内容がエクスポート時だけ漏れるということが起こりません) - 詳細地名(町名・施設名): Nominatim(OpenStreetMapの逆ジオコーディングAPI)へのオンデマンド問い合わせ(プライバシーモードOFF時、詳細パネルを開いたときのみ)
- 写真連携: Exif読み取りにexifr、ピンのクラスタ表示にLeaflet.markercluster(同梱・MITライセンス、
renderer/vendor/leaflet.markercluster/)。フォルダの再帰スキャンとメタデータ抽出はメインプロセスのWorker Thread(worker/photoScanWorker.js)内で行われ、UIをブロックしません
タイムラインのJSONは50MBを超えることがあるため、以下の設計にしています。
- ファイルの読み込み・JSON解析・都道府県/市区町村判定・クラスタリングはメインプロセスのWorker Thread(
worker/parseWorker.js)内で行われ、UIをブロックしません。パース中は進捗(読み込み中 / JSON解析中 / 正規化中 / 市区町村判定中 / クラスタリング中)を表示します。 rawSignals(分析に不要な生データ)は読み込み時に破棄し、正規化済みの軽量なデータ(滞在・移動・経路点の配列)のみをレンダラープロセスへ渡します。- 市区町村判定とクラスタリング結果は、入力ファイルのパス・サイズ・更新日時から作成したフィンガープリントをキーに、OS標準のユーザーデータフォルダ配下(
geo-cache/)にJSONとして保存されます(lib/geoCache.js)。同じファイルの2回目以降の起動では、このキャッシュがあれば再計算をスキップします。 - Nominatimの逆ジオコーディング結果も同フォルダにキャッシュされ、同一地点への再問い合わせは行いません。リクエストは1秒以上の間隔を空けて直列に送信し、Nominatimの利用規約に沿ったUser-Agentを設定しています。
- 除外ゾーンは、都道府県/市区町村の「訪問済み」判定・総距離や手段別/月別集計とは別に、ランキング・地図ピン・経路・訪問一覧向けのもう一段フィルタされたデータとして適用されます(
applyExclusionZones)。 - レンダラー側は
contextIsolation有効・nodeIntegration無効の安全な構成で、preload.jsが公開する最小限のAPI(window.pathBrowser)経由でのみメインプロセスと通信します。
main.js Electronメインプロセス(ウィンドウ生成・IPC)
preload.js contextBridge経由でレンダラーに安全なAPIを公開
worker/parseWorker.js タイムラインJSONの解析・正規化・都道府県/市区町村判定・
既定クラスタリング・経路セグメントの手段付与
worker/clusterWorker.js クラスタリングしきい値変更時の再計算
lib/prefectures.js 都道府県GeoJSONの読み込み・Point-in-Polygon判定
lib/municipalities.js 市区町村GeoJSONの読み込み・Point-in-Polygon判定・代表点算出
lib/cluster.js 距離ベースのクラスタリング(Union-Find)
lib/geoCache.js 市区町村判定・クラスタリング結果のディスクキャッシュ
lib/nominatim.js Nominatim逆ジオコーディング(レート制限・キャッシュ)
lib/exclusionZones.js 除外ゾーンの永続化(ユーザーデータフォルダ)
lib/coords.js 座標文字列パース・距離計算のユーティリティ
lib/photoCache.js 写真スキャン結果のディスクキャッシュ・連携フォルダの永続化
lib/thumbnailCache.js 生成済みサムネイルのディスクキャッシュ
worker/photoScanWorker.js 写真フォルダの再帰スキャン・Exif/Takeoutメタデータ抽出
worker/thumbnailWorker.js HEIC画像のデコード(libheif wasm)
data/prefectures.geojson 都道府県境界データ(同梱)
data/municipalities.geojson 市区町村境界データ(同梱)
renderer/mapView.mjs 制覇マップ描画(都道府県/市区町村、粒度切り替え、離島対応)
renderer/routeView.mjs 経路マップ描画
renderer/photoView.mjs 写真レイヤー描画(制覇マップ・経路マップ共通、クラスタ表示)
renderer/settingsView.mjs 除外ゾーン設定画面の描画
renderer/chronologyView.mjs 年表ビューの描画
renderer/statsView.mjs 移動統計ビューの描画
renderer/aggregate.mjs 集計・フィルタ・クラスタリング後処理ロジック(DOM非依存)
renderer/app.mjs 画面遷移・状態管理・イベント配線
electron-builderでWindows向けの配布物(NSISインストーラ・ポータブル版exe)を作成できます。
npm install
npm run distdist/フォルダにPathBrowser Setup <version>.exe(NSISインストーラ、デスクトップ/スタートメニューへのショートカット作成込み)が生成されます。コード署名をしていないため、配布先のPCで初回起動時にSmartScreenの警告が出ます。署名証明書を取得すればこの警告は解消できますが、個人利用や小規模な配布の範囲では必須ではありません。
開発者本人の実際のタイムラインデータ(数万件規模のセグメントを含む実データ)を使い、以下を確認しています。
- 読み込み〜正規化〜市区町村判定〜クラスタリング(初回数秒、キャッシュ利用時はさらに高速化)、複数の都道府県にまたがる訪問判定
- 都道府県クリック時、離島を持つ都道府県で本土ポリゴンに正しくフィットすることを境界データから直接検証(本土のbboxが離島側の座標を含まないことを確認)
- 粒度切り替え: 市区町村モードで全国1,894市区町村を描画し、地図のパン操作後も再描画がエラーなく行われることを確認
- 市区町村制覇率ランキング(都道府県別、全47件)とクリックによる市区町村マップへのジャンプ
- 年表ビュー(都道府県のみ/市区町村を含む、の切り替え、クリックでの地図遷移)
- 滞在時間の集計(よく行く場所ランキングの回数順/滞在時間順切り替えで順位が変わることを確認)
- 除外ゾーンの追加・削除、追加後にランキングの1位が変わること、非表示件数の表示、都道府県の訪問済みカウントがゾーン追加前後で不変であることを確認
- タイムラプス再生(月ごとにフィルタが自動で進み、地図とカウント表示が更新されることを確認)
- PNGエクスポート(実際にファイルが書き出されることを確認)
- 滞在地点詳細パネルでのNominatim詳細地名の取得(実際にAPIへの問い合わせが成功し、地名が取得できることを確認)
- クラスタリングしきい値スライダーの変更によるランキング再計算
- 経路マップ: 期間未指定時はメッセージ表示、年を指定すると手段別に色分けされたポリラインが描画されることを確認
- 移動統計(総距離・手段別内訳/所要時間/平均速度・月別積み上げグラフ・最長移動ランキング・曜日別/時間帯別/トップ5日の行動パターン)
- 年フィルタによる再計算と「その年に初めて訪れた県」表示
- 戻る/進むによるドリルダウン履歴のナビゲーション(クラスタ単位の滞在地点を含む)
- プライバシーモードON/OFFによるズーム制限・ピンの市区町村丸め・経路マップの無効化・自宅/職場周辺の除外・ランキングの市区町村集約の切り替え
- 配色: 塗りつぶしのfill-opacity/border色をSVG属性レベルで検証し、選択中の県のみ境界線がオレンジ・太線になること、ピン表示時に塗りつぶしの不透明度が下がることを確認。ピンが白縁取りのオレンジ(#ff7f0e)で描画されることも確認
- 詳細地名のランキング表示: パネルを開いた直後は表示中の行のみ「市区町村名(取得中…)」→取得完了後「詳細地名(市区町村名)」に差し替わること、スクロールで新たに見えた行が追加でキューに積まれること、パネルを離れると未処理分は破棄されるが取得済みキャッシュは残り再訪問時に即表示されることを確認(キャッシュ件数・キュー長を直接検証)
- 写真連携: 実際のGoogleフォトTakeoutエクスポートデータで、フォルダ連携・スキャン(Exif/Takeoutサイドカー双方からの位置情報取得)・制覇マップ/経路マップへのピン表示・クラスタ化・サムネイルポップアップ・ライトボックス表示までの一連の動作を確認
- 写真フォルダの大量ファイルスキャン: 列挙フェーズ(進捗が件数表示に切り替わること)→スキャンフェーズへの進捗表示の遷移、写真レイヤーの差分更新(無関係なナビゲーションで全ピンが再構築されずちらつかないこと、開いたポップアップが維持されること)を確認
- 写真クラスタのギャラリー: 最大ズームでクラスタをクリックするとサムネイルグリッドのポップアップ(4列・幅約400px)が開き、各サムネイルのクリックでライトボックスが開くこと。最大ズーム未満でのクラスタクリックはズームインになることを確認
- HEIC写真: HEICファイルのGPS・撮影日時がスキャンで取得されること、ポップアップ/ギャラリーでサムネイルが(初回は少し待って)表示されること、色味が正常なこと(BGRA/RGBA取り違えがないこと)を確認
- サムネイルキャッシュ: 同じ写真のポップアップを開き直すと即座に表示されること(
userData/thumbnail-cache/にJPEGが生成される)、設定画面のキャッシュクリアでサムネイル件数が報告され削除されることを確認 - 撮影地点の推定(Stage3): 位置情報のない写真がタイムラインの滞在中に撮られていれば滞在地点そのものに、移動中(2時間以内の記録が近くにある場合)は最も近い移動記録の地点に配置されること。推定ピンがダッシュ縁取り・半透明で実測ピンと視覚的に区別できること、ポップアップに推定である旨と時間差が表示されること、対応する記録が2時間以内に無い写真は(従来どおり)非表示のままであることを確認
PolyForm Noncommercial License 1.0.0。非営利目的での利用・改変・再配布は自由ですが、商用利用は許可されていません。詳細はLICENSEを参照してください。
本アプリは大学生が個人でAIとの対話を活用しながら開発したもの(いわゆるvibe coding)で、商用ソフトウェアと同等の品質保証・保守体制は前提としていません。不具合や改善点があればIssueで報告してもらえると助かります。