做有态度的前端团队

网易FEG前端团队

逐帧还是视频,如何选择

前言

最近在做一个游戏技能展示的效果,效果一般都有3s左右,鉴于效果复杂度只能通过逐帧或视频来实现展示。既然有两种实现方式,如何选择呢?先来简单分析下:
逐帧
所谓逐帧,就是把动画帧导出为图片,然后再用代码把没一帧的图片按照一定的频率进行切换,达到动画重组的播放效果。以3s的动画,每秒26帧的速度来计算,需要72张图片才能实现。同理如果帧数要求越高,需要的图片就越多。难度主要涉及到图片素材处理、图片资源加载、逐帧播放不掉帧等等
视频
视频这个没什么好说的,关键是看怎么播放。因为要达到的效果是看起来像一个页面动画而不是视频播放,所以要求是表面上看不出是视频播放即可。最大的难点也在于此,比如ios下是Safari下,页面的视频播放是会自动脱离页面全屏播放的。

视频代替逐帧的尝试

懒于对素材的处理以及确保动画播放更流畅,决定去尝试通过视频来实现,但最终这是一次失败的尝试,既然花时间尝试,也积累一些经验,在这简单分享下:

1、如何解决ios下视频全屏播放的问题
默认video标签实现的视频播放,在ios下都会全屏播放,脱离页面。
发现了webkit-playsinline这个好东西,只需要在video标签用上这个属性就能实现非全屏下播放视频:

<video webkit-playsinline="true" src="">
    <p>请在支持HTML5 video标签的浏览器中</p>
</video>

ios微信测试,恩,ok了!但是可悲的是目前Safari不支持该属性,听说ios10会支持...
那么Safari这个能解决吗?继续搜索,又发现一个好东西iphone-inline-video.browser.js(本次测试的最大惊喜,解决了多年的困惑!!!),已经有大神解决了这个问题。
插件地址:https://github.com/bfred-it/iphone-inline-video
引入插件后,只需要简单调用即可:

var video = document.querySelector('video');
makeVideoPlayableInline(video);

里面还提到用css干掉video默认居中的那个播放按钮:
320134870403082494.jpg

css代码如下:

.IIV::-webkit-media-controls-play-button,
.IIV::-webkit-media-controls-start-playback-button {
    opacity: 0;
    pointer-events: none;
    width: 5px;
}

其中上面的IIV是插件给video标签增加的class。
这样在ios基本可以实现完美内联播放视频了(其它什么UC,qq等等这些浏览器没做测试,有需要的自行测试)。

2、安卓下杂乱的表现
在安卓下情况就不乐观了,比如华为荣耀下的自带浏览器(下面没特殊指出都是测试机子的自带浏览器)会强制加上播放控制:
QQ截图20160628110221.png

也出现不支持-webkit-media-controls-play-button的情况,居中的播放按钮无法去除。还有一些手机检测到视频播放直接横屏全屏播放了。所以想保留video完美内联播放,安卓机子很多问题。
还有个致命点是,有些机子在播放视频时会把视频置为层级最高,上面无法再覆盖东西了。

那么可以借助canvas来画视频么?
大概的思路是:通过一个隐藏的video视频播放,然后通过一个按钮控制播放,用canvas来绘制画面出来。

<h2>video播放</h2>
<video webkit-playsinline="true" preload="auto" id="myvideo" src="">
    <p>请在支持HTML5 video标签的浏览器中</p>
</video>
<br>
<h2>canvas</h2>
<canvas id="mycanvas" width="400" height="225"></canvas>

<a href="javascript:;" id="Jplay">播放</a>

<script>
var myvideo=document.getElementById("myvideo");
//获取画布对象
var mycanvas=document.getElementById("mycanvas");
var playbtn=document.getElementById("Jplay");


playbtn.addEventListener('click', function () {
    if (myvideo.paused) {
        myvideo.currentTime = 0;
        myvideo.play();
        // requestAnimFrame(p);
    } else {
        myvideo.pause();
    }
});
var fps=30/1000;
setInterval(function(){
   mycanvas.getContext("2d").drawImage(myvideo,0,0,400,225);
},fps);

</script>

效果截图:
QQ截图20160628130416.png

demo测试地址》》

最终还是未能达到预期效果,在ios这种效果结合内联视频播放的处理,是正常的。但是在安卓下有些机子直接不支持canvas绘制视频,有些还是会全屏播放视频等等各种问题。

所以总得来说,这个尝试失败告终,最后还是通过逐帧来解决实际需求。但是Safari的内联解决方案还是收获不少~

手机阅读请扫描下方二维码:

已有 1 条评论

  1. ubee

    做仅需要在微信中传播的项目时,上述都可用~

添加新评论

ali-40.gifali-41.gifali-42.gifali-43.gifali-44.gifali-45.gifali-46.gifali-47.gifali-48.gifali-49.gifali-50.gifali-51.gifali-52.gifali-53.gifali-54.gifali-55.gifali-56.gifali-57.gifali-58.gifali-59.gifali-60.gifali-61.gif