您当前的位置:首页产经 >  >> 
012. vue 实现一个移动端横向滑动视频预览组件(精灵图)
来源:哔哩哔哩      时间:2023-08-01 12:12:47

前言

在互联网发展飞速的今天,诞生了许多在线观看视频的需求。由于视频往往较长,仅靠一个封面是无法较好地反映视频内容的,因此视频预览功能应运而生。

在 PC 端,当鼠标放到进度条上时就会出现缩略图来预览这个时间点的截图,现在很多视频网站都有这个功能。但在移动端,当手指放到进度条上时,在预览后视频进度也会相应跳转,这是我们不想看到的。为了解决这一问题,拟开发一移动端横向滑动视频预览组件。

实现

1.  缩略图生成


(相关资料图)

对于不同长度的视频,我们每隔一定时间,切出一帧作为视频缩略图。一般每隔 30s 截取一张,对于中长视频往往需要截取50张以上。大量的缩略图不利于存储、传输,在网络较差的情况下,加载需要较长时间,容易影响用户体验。故选择使用精灵图技术,即将多张缩略图合并在一张图片中的技术。

使用 ffmpeg 可以快速生成视频缩略图,在本文中生成的为 5x6 精灵图。对于示例中的 2G大小的 1080P 视频,切片后的单张缩略图仅有 600K 大小。

2. 缩略图展示

对于精灵图在网页中的显示,我们可以使用 background 属性控制图片的某一分片如何展示。

首先,我们需要一个放置所有缩略图的横向滚动父盒子,里面先放 3 个显示缩略图的子盒子:

当我们以 background-image 将图片引入时,我们会发现背景图片的第一片并没有贴合我们的盒子。这是因为浏览器还是以图片原始尺寸大小显示的,只不过多余部分被裁剪了而已。

因此我们需要将图片调整为宽是子盒子的 5 倍,高是子盒子的 6 倍,使用 background-size 的百分比控制。

这样以来,我们的背景图片大小就与子盒子有了比例关系,第一片也就正常显示了。

对于其它分片,仅需参照原点进行偏移即可,刚好 background-position 就提供了这个功能。

给定背景图像位置的百分比偏移量是相对于容器的。值 0% 表示背景图像的左(或上)边界与容器的相应左(或上)边界对齐,或者说图像的 0% 标记将位于容器的 0% 标记上。值为 100% 表示背景图像的 右(或 下)边界与容器的 右(或 下)边界对齐,或者说图像的 100% 标记将位于容器的 100% 标记上。因此 50% 的值表示水平或垂直居中背景图像,因为图像的 50% 将位于容器的 50% 标记处。类似的,background-position: 25% 75%表示图像上的左侧 25% 和顶部 75% 的位置将放置在距容器左侧 25% 和距容器顶部 75% 的容器位置。

基本上发生的情况是从相应的容器尺寸中减去背景图像尺寸,然后将结果值的百分比用作从左(或顶部)边界的直接偏移量。

(container width - image width) * (position x%) = (x offset value) (container height - image height) * (position y%) = (y offset value)

根据MDN 中的解释,我们可以计算出第  i 行 j 列的分片偏移值:

其中,m 与 n 分别为行列分片数量,在本文中,m=5, n=6。

任意选取第 3 行 4 列的分片,在第二个子盒子里展示:

对比原图,可以发现第 3 行 4 列的分片成功显示了出来。

3. 动态渲染

搞清楚了图片基本显示逻辑后,我们就可以在 vue 中实现其完整功能了。关键功能:监听当前显示分片索引并显示、前一张缩略图即将显示结束,提前拉取下一张渲染。

这两个功能,都使用 IntersectionObserver 来实现。对于第一个功能,监听所有缩略图,判断是否出现在 1% 的可视范围内,动态修改当前索引。

对于动态加载的实现,先计算出全部缩略图的分片偏移值、索引等信息,构造二维数组。组件初始仅渲染该数组第一张缩略图内的分片,监听到即将滚动到结尾时,推出剩余数组的第一张分片到渲染数组,利用 vue 的响应式数据绑定进行动态渲染。

监听加载逻辑如下:

组件 template内容:

最终效果如图所示:

延伸阅读

background - CSS:层叠样式表 | MDN:/zh-CN/docs/Web/CSS/background

IntersectionObserver - Web API 接口参考 | MDN:/zh-CN/docs/Web/API/IntersectionObserver

【重点】CSS之精灵图 - 知乎:/p/436792962

标签:

X 关闭

X 关闭