关于 leaflet-mapping
此技能介绍如何通过 Obsidian Leaflet 插件,在 Obsidian 笔记中声明式创建 Leaflet 地图。用户无需编写 JavaScript,即可呈现地理地图或自定义图片地图,并将标记关联到笔记数据。
主要功能
- 01通过 YAML 代码块参数定义地图
- 02支持真实地图和自定义图片地图
- 03从笔记、文件夹、标签及链接生成标记
- 04显示 GeoJSON、GPX 轨迹和覆盖层
- 05介绍分层地图及故障排查
适用场景
- 01绘制 Obsidian 笔记中记录的位置
- 02展示 GPX 文件中的路线
- 03用分层图片和标记构建奇幻地图
- 04根据带标签的笔记创建空间仪表板
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ zenobi-us/ dotfiles --skill leaflet-mapping安装后在 Claude Code 中输入/leaflet-mapping确认已加载。
详细介绍
Obsidian Leaflet 制图
概览
Obsidian Leaflet 插件支持使用 LeafletJS 创建交互式地图,无需编写 JavaScript。地图通过带有 YAML 参数的代码块定义,可显示现实世界中的位置(OpenStreetMap)、自定义图片(奇幻地图、楼层平面图),也可将两者叠加显示。 核心原则: 地图以声明式方式在 Markdown 代码块中定义。插件会处理所有 JavaScript,你只需配置参数。 插件: https://github.com/javalent/obsidian-leaflet
前提条件
必需:
- Obsidian Leaflet 插件(社区插件 → 搜索“Leaflet”) 可选(启用高级功能):
- Dataview 插件——使用
markerTag、filterTag、linksTo、linksFrom功能时必需 - 了解代码块所用 YAML 语法的基础知识
- 对于现实世界地图:从 Google Maps、OpenStreetMap 或 GPS 设备获取坐标
- 对于图片地图:知识库中的图片文件,以及已知的比例参考尺寸
快速入门:完整可用示例
目标: 创建一张显示所有带有 #visited 标签的笔记的地图
步骤 1:安装插件
- 设置 → 社区插件 → 浏览
- 搜索“Leaflet” → 安装 → 启用
- 搜索“Dataview” → 安装 → 启用(基于标签的标记必需)
- 重启 Obsidian(安装插件后建议重启)
步骤 2:创建测试笔记
创建
New York.md:
---
location: [40.7128, -74.0060]
---
# New York
My trip notes...
步骤 3:创建地图
创建 Travel Map.md:
```leaflet
id: my-travels
markerTag: #visited
height: 500px
```
预期结果: 地图会显示一个标记。点击标记 → 打开 New York 笔记。 如果标记没有显示: 请参阅下方的故障排除检查清单。
适用场景
在以下情况下使用此技能:
- 在知识库中创建基于位置的导航(世界地图、城市地图、建筑布局)
- 将笔记中的地理数据可视化(包含 frontmatter 位置的笔记)
- 显示带有标记的自定义图片地图(RPG 战役、故事场景)
- 使用 GPX 文件或 GeoJSON 追踪路线
- 构建带有空间数据的交互式仪表板 不适用于:
- 简单的图片显示(使用标准 Markdown)
- 复杂的 GIS 分析(使用专用 GIS 工具)
- 实时地图编辑(标记保存在插件数据中)
快速参考
基本地图结构
\`\`\`leaflet
id: unique-map-id # REQUIRED - any unique string
image: [[ImageFile.jpg]] # Image map (omit for real-world map)
lat: 50 # Initial latitude (center point)
long: 50 # Initial longitude (center point)
height: 500px # Map container height
width: 100% # Map container width
minZoom: 1 # Minimum zoom level
maxZoom: 10 # Maximum zoom level
defaultZoom: 5 # Initial zoom level
\`\`\`
地图类型
| 类型 | 参数 | 使用场景 |
|---|---|---|
| 现实世界地图 | 省略 image 参数 | OpenStreetMap、城市地图、GPS 数据 |
| 图片地图 | image: [[File.jpg]] | 奇幻地图、楼层平面图、自定义插画 |
| 多图层图片 | image: [[[Layer1]], [[Layer2]]] | 带有可切换叠加层的地图 |
| 自定义瓦片服务 | tileServer: <url>|<alias> | 替代地图样式(深色、卫星) |
创建标记
| 方法 | 语法 | 可编辑 | 使用场景 |
|---|---|---|---|
| 右键点击地图 | 交互式界面 | 是 | 手动放置标记 |
| 代码块 | marker: type,lat,long,link,desc | 否 | 文档中的固定标记 |
| 从笔记 frontmatter 添加 | markerFile: [[Note]] | 否 | 将单个笔记设为标记 |
| 从文件夹添加 | markerFolder: Path/To/Folder | 否 | 文件夹中的所有笔记 |
| 从标签添加 | markerTag: #location | 否 | 所有带有该标签的笔记(需要 Dataview) |
| 从链接添加 | linksTo: [[Note]] | 否 | 链接到该笔记或从该笔记链接的笔记(需要 Dataview) |
现实世界地图
默认瓦片服务为 OpenStreetMap。添加自定义瓦片服务以使用不同样式:
\`\`\`leaflet
id: city-map
tileServer: https://{s}.basemaps.cartocdn.com/dark_all/{z}/{x}/{y}{r}.png|Dark
tileServer: https://tiles.wmflabs.org/hillshading/{z}/{x}/{y}.png|Hills
osmLayer: false # Turn off default OpenStreetMap layer
\`\`\`
瓦片叠加层(替代完整图层):
tileOverlay: https://tiles.example.com/{z}/{x}/{y}.png|Overlay Name|on
添加 |on 可默认启用叠加层。
图片地图
关键第一步:设置边界
添加标记之前,请先定义边界,以免坐标混淆:
\`\`\`leaflet
id: fantasy-map
image: [[WorldMap.jpg]]
bounds:
- [0, 0] # Top-left corner
- [100, 100] # Bottom-right corner
\`\`\`
如果不设置边界,图片会拉伸以适配任意坐标。设置边界后,纬度和经度就能与图片像素形成可预测的对应关系。 常见的边界设置策略:
[0,0] to [100,100]——基于百分比(纬度和经度为百分比)[0,0] to [width,height]——基于像素(与图片尺寸一致)- 与源素材相匹配的自定义坐标系
多图层图像地图
叠加多个图像,每个图像使用独立的标记集:
\`\`\`leaflet
id: layered-map
image:
- [[BaseMap.jpg|Base Layer]]
- [[Roads.png|Roads]]
- [[Buildings.png|Buildings]]
\`\`\`
右上角的图层控制框可切换图层。标记按图层保存。
图像地图的缩放级别
反直觉的行为:maxZoom 越大,地图初始显示得越远。
**原因:**图像放置在 [0,0],并拉伸以适应地图。缩放级别控制的是底层地图,而不是图像缩放比例。
**解决方案:**先设置边界,再按需调整缩放级别。
bounds: [[0,0], [100,100]]
minZoom: 1
maxZoom: 6
defaultZoom: 3
zoomDelta: 0.5 # Finer zoom control
来自笔记的标记
**标记行为:**点击关联的标记会打开笔记(按 Ctrl/Cmd 并点击可在新窗格中打开)。通过 frontmatter 创建标记时,标记会自动关联到源笔记。
查找坐标
真实世界地图:
- Google Maps:右键点击位置 → 第一行显示坐标
- OpenStreetMap:点击“分享”按钮 → “Geo URI”中包含坐标
- GPS 设备:导出航点坐标 图像地图:
- 使用
bounds: [[0,0], [100,100]]设置百分比系统 - 设置边界后右键点击地图 → 点击时会显示坐标
- 反复试验:放置标记,然后在 frontmatter 中调整坐标
笔记 Frontmatter 格式
---
location: [lat, long] # REQUIRED for automatic markers (array format only)
mapmarker: custom-icon # Optional: marker type from settings
mapzoom: [minZoom, maxZoom] # Optional: visibility breakpoints
mapmarkers: # Optional: additional markers
- [type, [lat, long], "Description", minZoom, maxZoom]
- [type, [lat, long], "Another marker"]
---
**坐标格式:**必须是数组 [lat, long]。像 "40.7128, -74.0060" 这样的字符串不可用。
标记方法
单个笔记:
markerFile: [[LocationNote]]
文件夹(所有笔记):
markerFolder: Locations/Cities
markerFolder: Locations/Cities/ # Limit to top-level only (one slash)
按标签(⚠️ 需要 DATAVIEW 插件):
markerTag: #location # Notes with this tag
markerTag: [#city, #visited] # Notes with BOTH tags
markerTag:
- #location # Notes with #location OR
- [#city, #capital] # Notes with both #city AND #capital
**OR 逻辑:**使用多行 markerTag。**AND 逻辑:**使用数组 [#tag1, #tag2]。
筛选结果:
markerFolder: Locations
filterTag: #important # Only show important locations
根据链接关系(⚠️ 需要 DATAVIEW 插件):
linksTo: [[MainCity]] # All notes linking to MainCity
linksFrom: [[TravelLog]] # All notes linked from TravelLog
多个文件:linksTo: [[[File1]], [[File2]]]
自定义标记类型
在插件设置中定义,或在同一目录下的 markers.json 中定义:
[
{
"type": "city",
"icon": "building",
"color": "#FF0000",
"layer": true
},
{
"type": "dungeon",
"icon": "dungeon",
"color": "#8B4513",
"layer": true
}
]
然后在 frontmatter 中使用:mapmarker: city
覆盖层
用于表示影响范围、区域等的圆形覆盖层。
交互式创建
Shift + 右键 → 拖动 → 点击以设置半径
代码块定义
overlay: [color, [lat, long], radius unit, "description"]
示例:
overlay: [blue, [32, -89], 25 mi, 'Capital region']
overlay:
- ['rgb(255,0,0)', [50, 50], 10 km, 'Danger zone']
- ['#00FF00', [60, 60], 500 ft, 'Safe area']
**注意:**覆盖层按顺序绘制。较小的覆盖层若位于较大的覆盖层后方,将无法交互。
从笔记 Frontmatter 创建覆盖层
---
location: [50, 50]
mapoverlay: [blue, [50, 50], 25 km, "Influence zone"]
---
或者根据距离标签自动生成:
\`\`\`leaflet
overlayTag: influence
overlayColor: rgba(0,100,255,0.3)
\`\`\`
笔记 frontmatter:influence: 50 km
GeoJSON 和 GPX
GeoJSON
geojson: [[File.geojson]]|Optional Alias
geojson:
- [[Routes.geojson]]
- [[Regions.geojson]]|Regions|[[LinkedNote]]
geojsonColor: #FF0000 # Default color
GeoJSON 要素可以包含:
title、description或name→ 工具提示- MapBox SimpleStyle 属性 → 样式
- 按指定顺序绘制(图层顺序很重要)
GPX(GPS 轨迹)
gpx: [[Track.gpx]]
gpx:
- [[Hike1.gpx]]
- [[Hike2.gpx]]
gpxColor: #00FF00
gpxMarkers:
start: start-marker-type # From plugin settings
waypoint: waypoint-type
GPX 文件会显示:
- 路线(如果包含数据,则按速度/海拔/心率着色)
- 可选的起点/终点/航点标记
- 交互式数据点显示(点击轨迹)
常见模式
带有位置笔记的活动地图
\`\`\`leaflet
id: campaign-world
image: [[WorldMap.jpg]]
bounds: [[0,0], [100,100]]
markerFolder: Locations/Cities
markerFolder: Locations/Dungeons
markerTag: #location
filterTag: #visited
defaultZoom: 3
\`\`\`
使用 GPX 的旅行仪表板
\`\`\`leaflet
id: travel-routes
lat: 40
long: -100
gpxFolder: Travel/2024
gpxColor: #FF6600
gpxMarkers:
start: trip-start
waypoint: stop
\`\`\`
多图层奇幻地图
\`\`\`leaflet
id: kingdom-map
image:
- [[Base.jpg|Terrain]]
- [[Political.png|Borders]]
- [[Trade.png|Routes]]
bounds: [[0,0], [1000,1000]]
markerTag: #city
overlayTag: territory
overlayColor: rgba(100,100,255,0.2)
\`\`\`
常见错误
问题:标记在图像地图上显示的位置不正确
**原因:**未定义边界。没有边界时,Leaflet 会使用任意坐标空间,导致图像不可预测地拉伸。
**原因说明:**图像地图会将图像叠加到 Leaflet 的默认坐标系统上。未显式设置边界时,插件无法将你的坐标(例如 [50, 50])映射到图像上的特定像素。
修复方法:
- 放置任何标记之前,先设置边界:
bounds: [[0,0], [100,100]]
- 删除已有标记(它们使用了错误的坐标系统)
- 重新放置标记——现在标记会显示在你点击的位置 **查找图像上的正确坐标:**设置边界后,按 Shift 并点击地图以查看坐标,然后在 frontmatter 中使用这些坐标。
问题:无法充分放大/地图初始显示得太远
**原因:**图像地图的缩放控制的是底层地图,而不是图像缩放比例 修复方法:
- 设置与坐标系统相匹配的边界
- 调整
maxZoom(数值越小,默认视图越近) - 使用
zoomDelta: 0.5进行更精细的控制
问题:笔记中的标记未显示
快速诊断:
- 打开带有位置的笔记 → 查看 frontmatter 是否显示
location: [40.7128, -74.0060]?(数组格式) - 正在使用
markerTag/filterTag/linksTo/linksFrom?→ 是否已安装并启用 Dataview 插件? - 尝试重启 Obsidian(有时插件需要重启才能激活) 完整检查清单:
- 笔记的 frontmatter 中包含
location: [lat, long](确切格式:只能是数组,不能是字符串) - YAML(
tags: visited)和行内标签(笔记正文中的#visited)都能正常使用 - 坐标在地图边界内(检查最小/最大纬度和经度)
- 正在使用
markerTag、filterTag、linksTo或linksFrom?必须安装并启用 Dataview 插件(硬性依赖) - 验证 Dataview 是否正常工作:创建一个包含
dataview代码块的笔记,确认插件已激活 - 正在使用
filterTag?检查笔记是否包含所有必需标签 - 标记缩放断点(
mapzoom)是否在地图的minZoom/maxZoom范围内? - 对于真实世界地图:纬度/经度有效(纬度:-90 到 90,经度:-180 到 180)
- 对于图像地图:坐标符合你的边界系统
- 地图未指定
lat/long/defaultZoom?默认以 [50% 世界地图] 为中心。添加showAllMarkers: true可自动调整视野以显示所有标记。
问题:GeoJSON/GPX 文件未加载
原因:
- 文件路径不正确(使用维基链接
[[file.geojson]]或相对路径) - 大文件渲染较慢(检查控制台中的错误)
- GeoJSON 中存在 JSON 语法错误 解决方法: 在 https://geojsonlint.com/ 验证 GeoJSON
问题:叠加层无法交互 / 标记被叠加层遮挡
原因: 绘制顺序很重要。后绘制的叠加层和标记会显示在上方。 解决方法:
- 叠加层遮挡其他叠加层:在代码块中调整顺序(较大的叠加层放在最后)
- 叠加层遮挡标记:使用半透明颜色
rgba(255,0,0,0.3)或减小叠加层半径 - 标记位于叠加层下方:在代码块中,来自
markerTag/markerFolder的标记会在叠加层之后绘制
问题:自定义瓦片服务无法使用
检查清单:
- URL 包含
{z}、{x}、{y}占位符 - 服务允许公开访问(无需 API 密钥)
- 若要叠加在底图上,使用
tileOverlay而不是tileServer - 检查浏览器控制台中是否有 CORS 或 404 错误
距离和测量
显示两点之间的距离:
- 按住 Shift/Alt 并点击位置 1
- 按住 Shift/Alt 并点击位置 2
- 距离会显示在左下角的控制框中 比例尺和单位:
unit: miles # Display unit
scale: 1.5 # Scale factor for image maps
对于图像地图,测量图像上的已知距离并计算比例尺:
scale = real_distance / measured_pixel_distance
高级功能
从笔记设置初始视图
coordinates: [[CityNote]] # Note with location frontmatter
zoomTag: viewDistance # Read zoom from note's frontmatter
CityNote frontmatter:
location: [40, -100]
viewDistance: 50 miles
标记缩放断点
在不同缩放级别显示/隐藏标记(避免杂乱):
mapzoom: [3, 7] # Only visible between zoom 3-7
也可在代码块中为每个标记单独设置:
marker: city,40,-100,[[Note]],"Description",3,7
绘制模式
draw: true # Enable drawing tools
drawColor: #FF0000 # Default shape color
右键点击绘制的形状即可编辑/删除。形状会保存到地图实例中。
深色模式
darkMode: true # CSS filter inversion
通过针对 .leaflet-container .dark-mode 的 CSS 代码片段进行自定义
实际影响
社区中的使用场景:
- 桌面角色扮演游戏战役: 包含 100 多条地点笔记的世界地图,会随着玩家探索区域而自动更新
- 研究: 将 GeoJSON 数据集可视化,并关联分析笔记
- 旅行日志: 将来自 Apple Health 的 GPX 轨迹与作为标记的日志条目结合
- 城市规划: 建筑布局叠加不同楼层的图像
- 故事创作: 跟踪角色在整个剧情时间线中的位置 性能说明:
- 50 个以上标记:影响极小
- 200 个以上标记:加载时间有所增加
- 大型 GeoJSON/GPX 文件:考虑拆分文件
- 每条笔记中有多张地图:运行正常,各实例彼此独立