炫酷H5中序列图片视频化播放的高性能实现 « 张鑫旭

2,298 阅读7分钟
原文链接: www.zhangxinxu.com

这篇文章发布于 2018年05月1日,星期二,19:12,归类于 js实例。 阅读 3631 次, 今日 118 次

by zhangxinxu from www.zhangxinxu.com/wordpress/?…
本文可全文转载,但需要保留原作者和出处,摘要引流则随意。

一、爆款H5中的炫酷场景的技术实现

每年都会迸出一些爆款H5,这些H5通常会有一些酷酷的场景变换。

例如网易Julia H5。创意很棒,传播效果很广,其技术实现就相当简单粗暴,直接一个3分多钟的不带停顿的视频

类似使用视频的爆款H5还有很多,确实是一个非常不错的解决方案。

但是,视频的实现也有局限:

  1. iOS下不能自动播放,需要至少touch一次屏幕,这个有时候还挺烦人的,例如我们想做一个H5 app闪屏的时候就蛋疼了。
  2. 不能在中间穿插棒棒的交互效果,例如,需要视频某一帧暂停,鼠标hover或者touch的时候,当前画面有交互效果,就很不好处理。
  3. 播放的速率不能随心所欲控制,视频完成也就定死了。
  4. 如果有些信息是动态的,需要与用户信息关联,则视频方案也会面临很大的调整,因为总不可能每一个用户生成一个不一样的视频,需要辅助额外手段满足需求(例如CSS覆盖定位)。

此时又当如何处理呢?

我们可以使用序列图片,通过JS脚本,来模拟视频播放效果,以上所有局限将通通可以规避。

二、序列图片视频化技术实现方法很多

序列图片视频化技术实现方法很多,例如:

  1. 合在一张大图上,使用CSS3 animation控制background-position实现播放效果。此方法优点是方便快捷,但是,background-position定位性能不怎么样,只适用于小元素小动画,例如一些loading效果,如果是全屏的大图切换,则在移动设备上可以明显感觉到卡顿;
  2. 合在一张大图上,transform定位。性能还是撑不住;
  3. 图片一次性在页面上,依次控制显隐。性能有所提高,但如果图片序列上百帧,图片尺寸较大,性能还是撑不住,客户端说不定会直接闪退。
  4. 页面上一个<img>元素,然后不断改变src地址,不好意思,也不是很快。

总而言之,上面各种方法都是理论上可行,但实践下来的性能总不尽如人意。

那有没有什么高性能的实现方法呢?

有,一种是使用canvas绘图,但如果想要动态插入其他UI丰富的DOM结构(如登录模块),就比较麻烦;还有一种就是下面这个方法,实践下来性能可以,体验比较好,实现成本也不高。

三、序列图片视频化技术高性能实现方法

实现原理如下:

  1. 图片DOM对象预加载,放在内存中;
  2. 播放开始,页面append当前图片DOM,同时移除上一帧DOM图片(如果有),保证页面中仅有一个图片序列元素;

对,很简单,没什么高超的技巧,但就是这种实现策略,对页面的开销是上面几种方法中最小的,最终运行体验是最好的。

眼见为实,您可以狠狠地点击这里:序列图片实现视频播放效果demo

loading完毕,就可以看到一段播放效果——本人飞吻一枚:

张鑫旭的飒爽英姿

效果之流畅,体验之良好,十有八九都会认为是视频,其实不是,就是图片,不断的图片DOM增删实现的类似视频效果。

核心JS代码如下(完整代码见demo),假设container是容器元素,我们的图片已经预加载到store对象中,结构如下:

var store = {
    length: 47,
    1: img1,
    2: img2,
    ...
    47: img47    
};

则有:

var index = 1;
container.innerHTML = '';
// 依次append图片对象
var step = function () {
    if (store[index - 1]) {
        container.removeChild(store[index - 1]);
    }    
    container.append(store[index]);
    // 序列增加
    index++;
    // 如果不超过最大限制,播放下一帧
    if (index <= 47) {
        // 42是按照每秒24帧计算的值
        setTimeout(step, 42);
    }
};
step();

上面代码红色高亮是实现的关键,container.removeChild(store[index - 1])移除之前一帧图片DOM,container.append(store[index])则是插入当前一帧DOM,人的肉眼习惯连续性感知事物,因此,这种删除和添加,用户是无感知的,于是一个流程的播放效果即达成,根据实践,就算每帧图片在几百K大小主流设备也能hold住。

由于本质上播放的是DOM对象,因此,我们不仅可以播放图片DOM,还可以是有着丰富HTML结构的<div>元素,于是,什么样的交互实现都不在话下,比方说视频中要出现用户的姓名,怎么办,很简单啊,<div>元素中定位下就好了。

现在,技术实现已经对设计没有任何限制啦,剩下的就是产品和设计的创意,下一个爆款H5就是你了!

三、番外技能:如何把视频变成序列图片?

如果贵厂有设计师,让设计师处理,基本上,AE之类软件应该都了解。

如果没有设计师,要前端小伙伴自己处理,怎么办?

拿本文的序列图片举例,我是这么处理的:

  1. 手机视频QQ传到自己电脑;
  2. 打开Photoshop,然后:文件-导入-视频帧到图层,会出现一个窗口,可以剪切需要导入的视频范围;

    Photoshop中导入视频导入范围剪辑

    如果导入视频很长,建议先剪辑,再导入,除非你的电脑是iMac Pro这种级别的。

  3. 不做任何处理,直接:“文件-脚本-将图层导出到文件”;
  4. node.js小工具批量重命名了下(导出图片名称后面序号是准确序号),工具使用的JavaScript代码如下:
    var fs = require("fs");
    fs.readdir('./', function(err, files) {
        files.forEach(function(filename) {
            if (/jpg$/.test(filename) == false) { return; }
            // 确定新旧文件名称
            var oldPath = './' + filename, newPath = './' + filename.split(' ')[1];
            // 重命名走起
            fs.rename(oldPath, newPath, function() {
                console.log(filename + '重命名成功!');
            })
        });
    })

四、关于性能其他需要注意的

人眼的跟踪能力要比大猩猩之类要弱的,因此,实际开发,并不一定需要每秒24帧的播放速率,你每秒18帧,对于一个H5运营活动而言,用户是无感知的。每秒18帧的播放可以节约不少请求和加载数据量,性能上也能有所提高,权衡来看,是推荐的,毕竟我们不是去参加动画比赛,是一个在线的web产品。

设计师喜欢使用非常高清的图片,实际上,没有必要,注意度,2倍尺寸,30%~40%的图片质量足够了,效果也非常好,这也是经过实践的,大家如果和设计师意见不一致,就可以让她看我写的这段话。有效降低不必要的图片尺寸,可以大大节约内存的开销,也是可以提高播放的性能和品质的。

于是,三管齐下:高性能技术实现策略,适当降低帧率,优化图片尺寸,必定助你H5炫酷效果流畅至极,好评如潮,boss交口称赞!

以上就是本文内容,感谢阅读,如果文中有表述不准确的地方,欢迎指正!

大热书籍《CSS世界》签名版限量独家发售,显示我的专属购买码

(本篇完)// 想要打赏?点击这里。有话要说?点击这里

相关文章
    标签: HTML5, 优化, 动效, 序列图片, 性能, 视频