在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
相关产品推荐
相关产品推荐

