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实践课程系列的一部分,欢迎关注收藏

相关推荐
techdashen2 小时前
拆开任意 Electron 应用:从 Windows 安装包到 Discord 的私有更新协议
javascript·windows·electron
ZengLiangYi2 小时前
多格式文件解析:JSONL / SQLite / Event Stream
前端·javascript·后端
万少2 小时前
湖南卫视的秘密武器曝光!芒果灵创,专业AI影视创作平台
前端·javascript·后端
槑有老呆2 小时前
解密 JS 变量提升:告别玄学,读懂 V8 编译与代码执行逻辑
javascript
东风破_2 小时前
一文搞懂 JavaScript 变量声明:var、let、const 到底有什么区别?
前端·javascript
JasonSJX2 小时前
如何更好地保护视频内容免受盗版侵害
音视频·drm·视频加密·数字版权保护
无糖可可果2 小时前
拆穿 JavaScript 变量提升的"魔术"——从一段反直觉代码说起
javascript
月光刺眼2 小时前
🎶二分 · 双指针 · 滑动窗口 · 螺旋矩阵:数组算法四题拆解
javascript·算法
光影少年3 小时前
Redux Toolkit 用法、解决原生Redux 冗余问题
开发语言·前端·javascript·react.js·中间件·前端框架·ecmascript