You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

在Quarto HTML文档中添加Crosstalk实现Mapbox地图按需加载

使用Quarto + Crosstalk实现Mapbox地图动态切换

以下是实现需求的完整方案,包含代码示例和关键说明:

1. 完整Quarto文档代码

---
title: "交互式地图展示"
format: 
  html:
    page-layout: custom
---

```{r setup, include=FALSE}
library(crosstalk)

# 定义地图选项:替换为你的GitHub仓库中的GeoJSON链接
map_options <- data.frame(
  地图名称 = c("地震数据示例", "自定义地图1", "自定义地图2"),
  GeoJSON链接 = c(
    "https://docs.mapbox.com/mapbox-gl-js/assets/earthquakes.geojson",
    "https://raw.githubusercontent.com/你的用户名/你的仓库名/main/map1.geojson",
    "https://raw.githubusercontent.com/你的用户名/你的仓库名/main/map2.geojson"
  )
)

# 创建Crosstalk共享数据对象
shared_maps <- SharedData$new(map_options)

::: {.grid}

::: {.g-col-4}

地图选择器

# 下拉菜单版本(推荐)
filter_select(
  id = "map_selector",
  label = "选择要展示的地图:",
  sharedData = shared_maps,
  group = ~地图名称,
  multiple = FALSE
)

# 单选按钮版本(可选,替换上面的下拉菜单即可)
# filter_checkbox(
#   id = "map_radio",
#   label = "选择要展示的地图:",
#   sharedData = shared_maps,
#   group = ~地图名称,
#   multiple = FALSE
# )

:::

::: {.g-col-8}

地图展示区

<link href="https://api.mapbox.com/mapbox-gl-js/v2.11.0/mapbox-gl.css" rel="stylesheet">
<script src="https://api.mapbox.com/mapbox-gl-js/v2.11.0/mapbox-gl.js"></script>
<style>
#map { height: 600px; width: 100%; border-radius: 8px; }
</style>

<div id="map"></div>

<script>
mapboxgl.accessToken = '你的Mapbox令牌';
const map = new mapboxgl.Map({
  container: 'map',
  style: 'mapbox://styles/mapbox/satellite-v9',
  projection: 'globe',
  zoom: 2,
  center: [108, 4]
});

map.on('style.load', () => {
  map.setFog({});
});

// 核心函数:更新地图数据源
function updateMapSource(url) {
  if (map.getSource('dynamic-map')) {
    // 已存在数据源时直接更新数据
    map.getSource('dynamic-map').setData(url);
  } else {
    // 首次加载时添加数据源和图层
    map.addSource('dynamic-map', {
      type: 'geojson',
      data: url
    });
    map.addLayer({
      id: 'dynamic-map-layer',
      type: 'circle',
      source: 'dynamic-map',
      paint: {
        'circle-radius': 4,
        'circle-stroke-width': 2,
        'circle-color': 'red',
        'circle-stroke-color': 'white'
      }
    });
  }
}

// 初始化加载默认地图(下拉菜单版本)
document.addEventListener('DOMContentLoaded', () => {
  const selector = document.getElementById('map_selector');
  const initialUrl = selector.options[selector.selectedIndex].dataset.value;
  map.on('load', () => {
    updateMapSource(initialUrl);
  });
});

// 监听下拉菜单变化(下拉菜单版本)
document.getElementById('map_selector').addEventListener('change', (e) => {
  const selectedUrl = e.target.options[e.target.selectedIndex].dataset.value;
  updateMapSource(selectedUrl);
});

// ------------------------------
// 单选按钮版本的初始化和监听代码(替换上面的下拉菜单代码)
// ------------------------------
// document.addEventListener('DOMContentLoaded', () => {
//   const initialRadio = document.querySelector('input[name="map_radio"]:checked');
//   const initialUrl = initialRadio.dataset.value;
//   map.on('load', () => {
//     updateMapSource(initialUrl);
//   });
// });

// document.querySelectorAll('input[name="map_radio"]').forEach(radio => {
//   radio.addEventListener('change', (e) => {
//     if (e.target.checked) {
//       updateMapSource(e.target.dataset.value);
//     }
//   });
// });
</script>

:::

:::

## 2. 关键实现说明
- **Crosstalk共享数据**:通过`SharedData`将地图名称和对应的GeoJSON链接绑定,确保选择器和地图能联动
- **动态数据源更新**:`updateMapSource`函数处理两种场景:首次加载添加数据源,后续切换直接更新数据源内容,避免重复创建地图元素
- **事件监听**:通过原生JavaScript监听选择器的变化事件,实时获取选中的GeoJSON链接并更新地图

## 3. 注意事项
- 替换代码中的`你的Mapbox令牌`为实际令牌
- 替换`GeoJSON链接`列中的示例地址为你GitHub仓库中的实际文件链接
- 若使用单选按钮版本,注释掉下拉菜单相关代码,启用单选按钮对应的代码块

内容的提问来源于stack exchange,提问作者L Smeets
相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.11 01:31:08