/** * 旅程地图(v54 用户 2026-10-16 第 3 条)。 * * 用户原话:「你去读一下 TripLog 的代码,在旅程这个模块,可以在地图上显示旅程数据。 * 1. 先读一下它之前那个代码是怎么实现的,在我们的旅程模块也实现一下。」 * * ── 移植自 TripLog `templates/activities/index.php` 的那套(要点)── * · 高德 JS API 2.0;`AMap.Map` 建图 + `AMap.Marker` 打点; * · 每枚标记的 `position` 必须是 **[lng, lat] 数组**(传 `{lng,lat}` 裸对象 * 会让 AMap 抛错、整个绘制循环当场中断 —— TripLog 踩过这个,注释里写着 * "批 11 的光秃秃地图就是它"); * · `setFitView()` 自动框住所有点,但**上限 11 级**:只有一趟旅程时 * setFitView 会一路放大到街道级,那是导航视角、不是"足迹"视角; * · 卡片(自绘 content)用**方形画布 + 居中定位**,这样卡片可以偏离真实坐标 * 而不影响标记锚点(TripLog 用它做"同城扇开")。 * * ── 本版**不**做"同城扇开"(有意取舍)── * TripLog 那个扇开是为了"同一座城市的多次旅行挤在一起"。 * 本仓的旅程列表通常没有那么多趟、且每枚卡片更窄(只有标题+时间), * 先做"同一城市多点重合就按到达顺序错开一点"这种**轻量去重叠**即可 —— * 完整扇开(环形均匀分布 + 引线 + 与容器边界求解)是几百行几何代码, * 在没有真实数据压出这个问题之前不值得(TripLog 也是撞到了才写的)。 * * ⚠️ 合规:地图是高德(白名单内),SDK 由 layout.php 的 `fb-amap` 按需提供, * 本文件**不自己拼 SDK 地址、不碰 key**。 * ⚠️ SDK 未就位(没配 key / 加载失败)时降级成一句说明,不留白框。 */ (function () { 'use strict'; var el = document.getElementById('tripMapCanvas'); if (!el) { return; } var points; try { points = JSON.parse(el.getAttribute('data-points') || '[]'); } catch (e) { points = []; } if (!points || !points.length) { return; } function fallback(msg) { el.innerHTML = '
' + msg + '
'; } function esc(s) { return String(s === null || s === undefined ? '' : s) .replace(/&/g, '&').replace(//g, '>').replace(/"/g, '"'); } /* 视野上限:别放到街道级(见文件头的说明) */ var MAX_ZOOM = 11; /* 卡片画布:内容绝对居中,卡片可以在这块画布里自由偏移(本版只用于微错开) */ var CANVAS = 260; var C = CANVAS / 2; function boot() { var map = new AMap.Map(el, { viewMode: '2D', zoom: 5, resizeEnable: true }); /* 轻量去重叠:同一位置的多个点(坐标差 < 极小阈值)沿一个方向的螺旋微移, 免得完全重合、只能点到一个。位移**只改卡片绘制位置**, 若做不明显,至少保证每枚都能被点到(content 是各自的 DOM)。 */ var seen = {}; var markers = []; points.forEach(function (p, i) { var key = p.lng.toFixed(3) + ',' + p.lat.toFixed(3); var n = seen[key] = (seen[key] || 0); seen[key]++; var dx = 0, dy = 0; if (n > 0) { // 螺旋微移:每多重一个,就往外挪一点(角度按 n 递增) var ang = n * (Math.PI / 3); var rad = 26 + n * 6; dx = Math.cos(ang) * rad; dy = Math.sin(ang) * rad; } /* 🔴 v63(用户 2026-10-19 第 3 条):「旅程地图模式,应该显示旅程的题图。」 ⇒ 卡片左侧一枚 40×40 的题图(`trip_details.cover_key` → 服务端算好的 URL, 见 _map_body.php)。没有题图就**只显示文字**,不摆灰色占位方块 (地图上每枚卡片都带一个灰框,整张图会显得脏)。 */ var thumb = p.cover ? '