mcpField
L
leaflet-mapping

leaflet-mapping

github.com/zenobi-us生产力6873 次安装今天更新
代码仓库

关于 leaflet-mapping

此技能介绍如何通过 Obsidian Leaflet 插件,在 Obsidian 笔记中声明式创建 Leaflet 地图。用户无需编写 JavaScript,即可呈现地理地图或自定义图片地图,并将标记关联到笔记数据。

主要功能

  1. 01通过 YAML 代码块参数定义地图
  2. 02支持真实地图和自定义图片地图
  3. 03从笔记、文件夹、标签及链接生成标记
  4. 04显示 GeoJSON、GPX 轨迹和覆盖层
  5. 05介绍分层地图及故障排查

适用场景

  1. 01绘制 Obsidian 笔记中记录的位置
  2. 02展示 GPX 文件中的路线
  3. 03用分层图片和标记构建奇幻地图
  4. 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:安装插件

  1. 设置 → 社区插件 → 浏览
  2. 搜索“Leaflet” → 安装 → 启用
  3. 搜索“Dataview” → 安装 → 启用(基于标签的标记必需)
  4. 重启 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])映射到图像上的特定像素。 修复方法:

  1. 放置任何标记之前,先设置边界:
bounds: [[0,0], [100,100]]
  1. 删除已有标记(它们使用了错误的坐标系统)
  2. 重新放置标记——现在标记会显示在你点击的位置 **查找图像上的正确坐标:**设置边界后,按 Shift 并点击地图以查看坐标,然后在 frontmatter 中使用这些坐标。
问题:无法充分放大/地图初始显示得太远

**原因:**图像地图的缩放控制的是底层地图,而不是图像缩放比例 修复方法:

  1. 设置与坐标系统相匹配的边界
  2. 调整 maxZoom(数值越小,默认视图越近)
  3. 使用 zoomDelta: 0.5 进行更精细的控制
问题:笔记中的标记未显示

快速诊断:

  1. 打开带有位置的笔记 → 查看 frontmatter 是否显示 location: [40.7128, -74.0060]?(数组格式)
  2. 正在使用 markerTag/filterTag/linksTo/linksFrom?→ 是否已安装并启用 Dataview 插件?
  3. 尝试重启 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 文件:考虑拆分文件
  • 每条笔记中有多张地图:运行正常,各实例彼此独立

评论

支持 Markdown