爱客仕-前端团队博客园

css3模拟视频以解决video弊端

先说我的需求,一进页面的时候播放视频动效,播放完毕后弹出相应的文字及按钮。
听着好像一个很简单的需求,立马也有清晰的思路:用video标签在页面上引入视频,全屏全屏全屏播放!!给video加个完成事件,让隐藏的文本按钮显示,over ~~~

一切听起来so easy,但做的第一步就发现了video的坑。video的宽高设置为页面的100%,页面一进来就自动播放, 结果ios上就自动弹出播放了,安卓上无法自动播放,且播放时弹出,播放完毕还有小广告,天了撸 ~~~ 求助百度、谷歌。。。。

关于视频的弊端

1
2
<video autoplay width="100%" height="100%" x-webkit-airplay="true" webkit-playsinline="" playsinline="true" preload="none" src="">
</video>

google及参照其他网站的解决方案,发现在我的iphone 6 解决了弹出播放的问题,且微信及其他浏览器内正常

可是!!!
其他型号的手机及安卓问题并没有解决

总结一下video的坑:

  • IOS上不同型号不同系统版本,暴露的问题都不一样。有些弹出播放,有些能嵌入在页面上播放(我希望是嵌在页面内播放)
  • 安卓机中无法自动播放,必须点击后弹出播放,且播放完成后会弹出广告
  • 播放完成后点击其他页面,再返回,操作几遍后视频变黑,但实际是在播放中,因为播放完成事件有执行。
  • 以上是微信上暴露的问题,其他浏览器下某些问题又是好的

解决方案一:gif替换视频

视频实在是暴露太多问题,尤其是在微信上,而我们当前的需求是用户微信扫二维码展示页面,所以一直PASS视频,想其他的招

想到的第一个解决方案是gif,但gif也有很多弊端

  • 无法获取gif完成的时间点,只能大致估算
  • 因为全屏关系,gif所占空间较大,最差的画质也差不多,且画质不清晰很影响视觉效果。

最终解决方案:css3动画模拟视频

可参照张鑫旭的例子 http://www.zhangxinxu.com/study/201512/gif-stop-and-play-by-css3-animation.html

直接按照他的案例其实很好做,只要UI提供一张长图就OK了,但有几个点需要注意

  • 微信对图片的大小是有限制的,不仅所占空间有限制,宽度和高度若太大也会使微信闪退
  • 因为我们是全屏展示,所以一张张图肯定是会让微信崩塌的,需要几张得,一张有几帧需要计算好
  • 部分内存比较小的手机,经过无数次的动画刷新(图片已经很大了,动画也会消耗内存),整个页面的所占的空间越来越大会使微信闪退

经过我和UI的压力测试,发现宽度超过1W像素微信就闪退了。且图片得小于50张以下,而且为了能让100整除取10张图,每张图里有4帧

1
2
3
4
5
6
7
8
9
10
11
12
<div class="video" v-show="ios">
<div class="part01"></div>
<div class="part02"></div>
<div class="part03"></div>
<div class="part04"></div>
<div class="part05"></div>
<div class="part06"></div>
<div class="part07"></div>
<div class="part08"></div>
<div class="part09"></div>
<div class="part10"></div>
</div>

下面是对应的样式,因为是全屏播放且总共有40帧,所有整个宽度为4000%,由有10个div左浮动连接而成一张大图,每个div占总宽度的10%; 用transform: translateX让他从0移动到最后

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
.video {
width 4000%
height 100%
animation: play steps(40) 2s infinite both
animation-iteration-count: 1
@keyframes play {
0% {
transform translateX(0%)
}
100% {
transform translateX(-100%)
}
}
div {
width 10%
height 100%
float left
&.part01 {
background url("~assets/images/part-1.jpg") no-repeat 0 -40px
background-size 100% auto
}
&.part02 {
background url("~assets/images/part-2.jpg") no-repeat 0 -40px
background-size 100% auto
}
&.part03 {
background url("~assets/images/part-3.jpg") no-repeat 0 -40px
background-size 100% auto
}
&.part04 {
background url("~assets/images/part-4.jpg") no-repeat 0 -40px
background-size 100% auto
}
&.part05 {
background url("~assets/images/part-5.jpg") no-repeat 0 -40px
background-size 100% auto
}
&.part06 {
background url("~assets/images/part-6.jpg") no-repeat 0 -40px
background-size 100% auto
}
&.part07 {
background url("~assets/images/part-7.jpg") no-repeat 0 -40px
background-size 100% auto
}
&.part08 {
background url("~assets/images/part-8.jpg") no-repeat 0 -40px
background-size 100% auto
}
&.part09 {
background url("~assets/images/part-9.jpg") no-repeat 0 -40px
background-size 100% auto
}
&.part10 {
background url("~assets/images/part-10.jpg") no-repeat 0 -40px
background-size 100% auto
}
}
}

因为图片实在是太多也太大必须得让图片加载完成后再加载动画,这里只判断了ios(安卓不做动画,直接放死图)

1
2
3
4
5
6
7
8
9
10
11
12
13
if (this.ios) {
let count = 10
let imgsrc = [part01, part02, part03, part04, part05, part06, part07, part08, part09, part10]
imgsrc.forEach((src, index) => {
let img = new window.Image()
img.src = src
img.onload = () => {
if (index + 1 >= count) {
this.playVideo = true
}
}
})
}


上面的gif还是我自己PS做的。效果与我做的css3动效一样。

为什么安卓不播放动效呢,是因为安卓机上css3始终有卡顿所以产品觉得直接PASS了

另外要说一点animation若你只想播放一次时,它播放完毕后会返回为初始状态,这一点很蛋疼,此项目我在底部放了一张底图,播放完毕后展示底图。底图的另外个好处时安卓不播放动画也就直接显示底图了,不需多加div。

之后我会分享如何解决animation的一些弊端