MapLibre GL JS第30课:添加视频

📌 学习目标

  • 掌握添加视频的实现方法
  • 理解相关API的使用
  • 能够独立完成类似功能开发

🎯 核心概念

将视频添加为地图上的动态图层。

💻 完 整 代 码

代码示例

js 复制代码
const videoStyle = {
    'version': 8,
    'sources': {
        'satellite': {
            'type': 'raster',
            'url': 'https://api.maptiler.com/tiles/satellite/tiles.json?key=get_your_own_OpIi9ZULNHzrESv6T2vL',
            'tileSize': 256
        },
        'video': {
            'type': 'video',
            'urls': [
                'https://static-assets.mapbox.com/mapbox-gl-js/drone.mp4',
                'https://static-assets.mapbox.com/mapbox-gl-js/drone.webm'
            ],
            'coordinates': [
                [-122.51596391201019, 37.56238816766053],
                [-122.51467645168304, 37.56410183312965],
                [-122.51309394836426, 37.563391708549425],
                [-122.51423120498657, 37.56161849366671]
            ]
        }
    },
    'layers': [
        {
            'id': 'background',
            'type': 'background',
            'paint': {
                'background-color': 'rgb(4,7,14)'
            }
        },
        {
            'id': 'satellite',
            'type': 'raster',
            'source': 'satellite'
        },
        {
            'id': 'video',
            'type': 'raster',
            'source': 'video'
        }
    ]
};

const map = new maplibregl.Map({
    container: 'map',
    minZoom: 14,
    zoom: 17,
    center: [-122.514426, 37.562984],
    bearing: -96,
    style: videoStyle
});

let playingVideo = true;

map.on('click', () => {
    playingVideo = !playingVideo;

    if (playingVideo) map.getSource('video').play();
    else map.getSource('video').pause();
});

代码示例

html 复制代码
<!DOCTYPE html>
<html lang="en">
<head>
    <title>Add a video</title>
    <meta property="og:description" content="在卫星栅格底图上显示视频。" />
    <meta property="og:created" content="2025-06-25" />
    <meta charset='utf-8'>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel='stylesheet' href='https://unpkg.com/maplibre-gl@5.24.0/dist/maplibre-gl.css' />
    <script src='https://unpkg.com/maplibre-gl@5.24.0/dist/maplibre-gl.js'></script>
    <style>
        body { margin: 0; padding: 0; }
        html, body, #map { height: 100%; }
    </style>
</head>
<body>
<div id="map"></div>
<script>
    const videoStyle = {
        'version': 8,
        'sources': {
            'satellite': {
                'type': 'raster',
                'url': 'https://api.maptiler.com/tiles/satellite/tiles.json?key=get_your_own_OpIi9ZULNHzrESv6T2vL',
                'tileSize': 256
            },
            'video': {
                'type': 'video',
                'urls': [
                    'https://static-assets.mapbox.com/mapbox-gl-js/drone.mp4',
                    'https://static-assets.mapbox.com/mapbox-gl-js/drone.webm'
                ],
                'coordinates': [
                    [-122.51596391201019, 37.56238816766053],
                    [-122.51467645168304, 37.56410183312965],
                    [-122.51309394836426, 37.563391708549425],
                    [-122.51423120498657, 37.56161849366671]
                ]
            }
        },
        'layers': [
            {
                'id': 'background',
                'type': 'background',
                'paint': {
                    'background-color': 'rgb(4,7,14)'
                }
            },
            {
                'id': 'satellite',
                'type': 'raster',
                'source': 'satellite'
            },
            {
                'id': 'video',
                'type': 'raster',
                'source': 'video'
            }
        ]
    };

    const map = new maplibregl.Map({
        container: 'map',
        minZoom: 14,
        zoom: 17,
        center: [-122.514426, 37.562984],
        bearing: -96,
        style: videoStyle
    });

    let playingVideo = true;

    map.on('click', () => {
        playingVideo = !playingVideo;

        if (playingVideo) map.getSource('video').play();
        else map.getSource('video').pause();
    });
</script>
</body>
</html>

🔍 代码解析

1. 配置样式对象

定义完整的样式对象,包含多个数据源和图层:

  • satellite: 卫星影像栅格源
  • video: 视频源

2. 配置视频数据源

style.sources 中定义视频源:

  • type: 'video': 指定为视频源
  • urls: 视频文件URL数组(支持多种格式)
  • coordinates: 视频四角对应的地理坐标

3. 配置图层

创建三个图层:

  • background: 背景层
  • satellite: 卫星影像层
  • video: 视频层(叠加在卫星影像上)

4. 初始化地图

使用配置的样式对象创建地图实例,设置初始视角。

5. 添加点击交互

点击地图切换视频播放/暂停状态。

⚙️ 参数说明

参数 类型 必填 说明
container string 地图容器ID
style object 完整的样式对象
center number, number 初始中心点,默认0, 0
zoom number 初始缩放级别,默认0
bearing number 初始方位角

视频源配置

属性 类型 说明
type string 必须为 'video'
urls array 视频文件URL数组
coordinates array 四角地理坐标数组 左下, 右下, 右上, 左上

🎨 效果说明

运行代码后:

  • 地图显示美国旧金山区域(中心点 -122.51°W, 37.56°N)
  • 卫星影像作为底图
  • 无人机航拍视频叠加在指定地理区域
  • 点击地图可播放/暂停视频
  • 用户可正常交互(拖拽、缩放、旋转)

💡 常 见 问 题

Q1: 视频坐标如何设置?

A: coordinates 数组按顺序定义视频四角的地理坐标:左下、右下、右上、左上。

Q2: 如何支持多种浏览器?

A: 提供多种格式的视频文件(MP4、WebM等),浏览器会自动选择支持的格式。

Q3: 如何控制视频播放?

A: 通过 map.getSource('video').play()pause() 方法控制。

📝 练习任务

  1. 基础练习:修改视频URL,更换为其他视频
  2. 进阶挑战:添加视频进度条控制
  3. 拓展思考:如何实现多个视频图层切换?

🌟 最佳实践

  1. 格式兼容: 提供多种视频格式确保跨浏览器支持
  2. 坐标准确: 确保视频坐标与实际地理位置匹配
  3. 交互友好: 提供清晰的播放控制方式
  4. 性能优化: 视频尺寸适中,避免过大影响加载速度

🔗 延伸阅读


本文是MapLibre GL JS实践课程系列的一部分,欢迎关注收藏

相关推荐
一颗烂土豆5 小时前
Meshopt 压缩深度解析,为什么它比 Draco 更快
前端·javascript·webgl
kyriewen8 小时前
同事每天催我 Code Review,我写了个脚本让 AI 替我 review PR——现在他反过来催 AI 了
前端·javascript·ai编程
weedsfly10 小时前
迭代器、生成器与异步迭代——让数据“按需流动”的艺术
前端·javascript
假如让我当三天老蒯11 小时前
前端跨域解决方案(学习用)
前端·javascript·面试
铁皮饭盒12 小时前
Bun 哪比 Node.js 快?
javascript·后端
JieE21220 小时前
LeetCode 56. 合并区间|超清晰 JS 图解思路,面试高频区间题
javascript·算法·面试
candyTong1 天前
RTK 技术原理:一次典型会话里,80% 上下文是怎么省下来的
javascript·后端·架构
_柳青杨1 天前
深入理解 JavaScript 事件循环
前端·javascript
大家的林语冰1 天前
ES5 凉凉,Babel 8 正式发布,默认不再编译为 ES5 和 CJS......
前端·javascript·前端工程化
weedsfly1 天前
异步编程全景与事件循环——彻底搞懂 JS 执行机制
前端·javascript