前言
作为前端同学,或多或少都会接到动画需求。目前动画效果越来越酷炫,动画的绘制难度也逐渐增大。
前段时间主要学习了 APNG、Lottie、Video 三种动画方案。其中 APNG、Lottie 篇主要分享如下:
在上述两篇文章中都各自讲述了 APNG、Lottie 的原理、优缺点等,今天要讲的主题是 Video 实现动画。也就是通过播放一段视频来实现动画。
Video
HTML 元素 用于在HTML或者XHTML文档中嵌入媒体播放器,用于支持文档内的视频播放。
笔者在一次需求中与设计同学讨论时,发现一段 AE 制作的动画,无损导出后的大小如下:
- APNG 大小 27M
- Video 仅有 400K
然而在网上查找资料,发现 Video 各种各样的坑,可以看下这篇复杂帧动画之移动端video采坑实现。
除了常见的播放等问题,还有一个最大的问题就是,Video 没有 Alpha 通道,也就是如下效果所示,视频背景是黑乎乎的。
然而我们平时的动画场景基本都是需要透明度的,所以这种方案夭折。继续查找资料发现,可以通过 WebGl 来绘制透明视频。
WebGl + Animation
WebGl 概念:
WebGL(Web图形库)是一个 JavaScript API,可在任何兼容的 Web 浏览器中渲染高性能的交互式 3D 和 2D 图形,而无需使用插件。WebGL 通过引入一个与 OpenGL ES 2.0 非常一致的 API 来做到这一点,该 API可以在 HTML5 canvas 元素中使用。 这种一致性使 API 可以利用用户设备提供的硬件图形加速。
再来回顾下动画的概念:
动画(英语:Animation)是一种通过定时拍摄一系列多个静止的固态 图像(帧)以一定频率连续变化、运动(播放)的速度(如每秒16张)而导致肉眼的视觉残象产生的错觉,而误以为图画或物体(画面)活动的作品及其视频技术。
由于 WebGL 需要一定的入门才能理解代码,所以接下来只会讲下思路,具体代码细节可以实战时再去学习。所以遇到不懂的代码不要过于纠结,理解思路才是最重要的。
WebGl 实现透明视频绘制的主要思路为:
- 解析 Video 视频播放过程的每一帧
- 识别每一帧需要透明的区域,并设置为透明
- 通过 WebGl 绘制处理后的每一帧
- 以上过程重复至视频播放结束,快速绘制过程产生连续变化,为新的带有透明度的动画
WebGl 实现透明视频绘制
解析 Video 视频播放过程的每一帧和绘制每一帧其实都是由 WebGL 的 API 就可以轻松完成。所以重点是了解如何识别每一帧需要透明的区域,并设置为透明。
针对以下视频,最简单的方案就是识别下黑色,然后绘制成透明。但是如果动画也有黑色元素,那么就会误杀。所以这个方案初步不行。
第二个方案就是需要设计同学导出左右对称视频 查看视频 如下:
这个视频中是左右对称的。左面是纯白色的动画,右面是有色彩的也是我们所需要的动画。那我们的绘制思路就可以为:
- 真正绘制的动画宽为原视频的 50%,也就是一半,高和视频一致
- 解析左侧像素点,白色就代表是动画,黑色就代表需要透明
- 解析右侧像素点的
rgb
- 绘制时色值变为
rgba
,那么a
的值就是左侧的白色1
(该像素颜色不变)或是黑色0
(该像素颜色变为透明)
precision lowp float;
varying vec2 v_texCoord;
uniform sampler2D u_sampler;
void main(void) {
gl_FragColor = vec4( // vec4代表4维变量,因为rgba是4个值
texture2D(u_sampler, v_texCoord).rgb, // 右侧的rgb
texture2D(u_sampler, v_texCoord + vec2(-0.5, 0)).r // -0.5代表画布左侧,取值是rgb中的r值
);
}
上述 WebGl 代码就是透明度的核心代码,当然第一次接触 WebGl 的人肯定就懵了(我也是)。所以我们主要是理解思路即可,理解这个思路,完全可以用 canvas 实现同样的效果。
实现代码及效果可以直接看 Demo,代码不做过多讲解了。
本方案依赖视频自动播放,所以兼容性问题不是很好解决,适合 APP 内的一些场景(比如直播礼物等)。
总结
将之前的学习做了一个简单的总结
下面是每种方案的一些情况总结和对比。
讲解不对的地方欢迎指正,多多探讨~