YAMAPの登山計画書閲覧ページからルート情報をgeojsonで取得するscript
2023-10-07 14:23:41 使えなくなっていた
__NUXT__にルートデータが含まれなくなった
https://api.yamap.com/plans/:plan_id/track を使わないとトラックデータを取得できない
しかもこの中には時刻情報が含まれない。コードを解析してどのように時刻を再現しているか探らないといけない
YAMAPの登山計画書からルートデータをgeojson形式で取得するscript
YAMAPの計画書のルートを地理院地図の作図機能で取り込みたかったので作った
使い方
下記のscriptを登山計画書ページから開発コンソールに貼り付けて実行する
geojsonのdownload windowが表示されるので、それを保存する
備考
propertiesは地理院地図の規格に準拠している
geojsonの規格とはズレがあるので注意
ラベルの位置は手動で調整すること
からくり
YAMAPのwebサイトはNuxt.jsで組まれている
Nuxt.jsは、どうやら内部で使っているデータをwindow.__NUXT__に露出しているらしい
この中に表示している登山計画書のデータが含まれているので、そこからルート座標を取り出してgeojsonを作ればいい
同じ原理で、KMLなどももちろん作成できる
実装したいこと
も表示する?
バグ
✅コースタイム倍率を1.0以外にすると、到着時刻がおかしくなる
計算が難しい
修正済み
2022-10-15 20:56:58 まだずれてるかも
そのうち確認する
2022-10-15
20:38:07 「分岐」という名前のラベルを除外した
2022-08-09
12:45:17
各地点の到着時刻も表示する
座標が地点名と重なっているので、適宜手動で動かすこと
自動でずらすのは難しいtakker.icon
縮尺によって緯度の移動量が変化するため
ファイル名に計画書のタイトルを使う
スタイルは適宜調整すること
code:js
{
const plan = __NUXT__.data0.plan;
const rootName = plan.title; // 適宜変更する
const root = plan.coords;
const startAt = new Date(plan.start_at * 1000);
// 前のポイントからの移動時間を計算するのに必要な変数
let cursor = new Date(startAt);
let prev = 0;
/** @type {{ coord: number[]; name: string; arrived: Date; stayTime: number; }[]}
*
* stayTimeの単位は秒
*/
const checkpoints = plan.checkpoints.flatMap((point) => {
const coord = point.landmark.coord;
const name = point.landmark.name;
/** その日の最初のポイントかどうか */
const isStart = point.cumulative_down === 0 && point.cumulative_up === 0;
const now = point.arrival_time_in_seconds;
const arrived = !isStart ?
new Date(cursor.getTime() + Math.round((now - prev) * 1000 * plan.time_multiplier)) :
new Date(startAt.getTime() + now * 1000);
arrived.setDate(arrived.getDate() + point.arrival_day_number - 1);
prev = now + point.stay_time;
cursor = new Date(arrived.getTime() + point.stay_time * 1000);
return { coord, name, arrived, stayTime: point.stay_time };
});
const zero = (n) => ${n}.padStart(2, "0");
const toHHMM = (date) => ${zero(date.getHours())}:${zero(date.getMinutes())};
const geoJson = {
type: "FeatureCollection",
features: [
{
type: "Feature",
properties: {
name: rootName,
_color: "#56a066",
_opacity: 1,
_weight: 3,
},
geometry: {
type: "LineString",
coordinates: root,
},
},
// 通過点の図形情報
...checkpoints.flatMap(({
coord, name, arrived,
}) => {
const geometries = [
{
type: "Feature",
properties: {
_markerType: "Icon",
// よくある逆しずく形のアイコン
_iconUrl: "https://maps.gsi.go.jp/js.lib/leaflet-1.2.0/images/marker-icon-2x.png",
// そのままだと大きいので、1/2に縮小する
_iconSize: 25, 41,
// 逆しずくの脚部分をアンカーにする
_iconAnchor: 12.5, 41,
},
geometry: {
type: "Point",
coordinates: coord,
},
},
{
type: "Feature",
properties: {
_markerType: "DivIcon",
_html: <div style=\"font-size:12pt;font-weight:bold;\">${toHHMM(arrived)}</div>,
},
geometry: {
type: "Point",
coordinates: coord,
},
},
];
if (name !== "分岐")geometries.push(
{
type: "Feature",
properties: {
_markerType: "DivIcon",
_html: <div style=\"font-size:18pt;font-weight:bold;\">${name}</div>,
},
geometry: {
type: "Point",
coordinates: coord,
},
}
);
return geometries;
}),
],
};
const url = URL.createObjectURL(new Blob(
JSON.stringify(geoJson),
{ type: "application/json" },
));
const a = document.createElement("a");
a.href = url;
a.download = ${rootName}.geojson;
a.style.display = "none";
document.body.append(a);
a.click();
a.remove();
}
#2023-10-07 14:25:22
#2022-10-15 20:38:02
#2022-08-25 15:22:21
#2022-08-09 12:45:04
#2022-08-03 15:40:37