zoukankan      html  css  js  c++  java
  • 连续大背景的处理

    搞一个高端的用户体验,在精度上总不能太寒碜,但是又怕用户等不了,怎么办?一开始加载的时候,他们为大家准备了一个 3D 弹球游戏,在一定程度上减弱了用户等待的焦虑感。但是网站内里太大太慢也是不行的,真功夫还是要拿出来的。

    问题是背景,该用图片序列还是视频?一般经验告诉我们,像这种全景的东西,顺放倒放的,肯定都是用序列:flv倒放会卡。比如经典的IEKA网站用的就是图片序列。但是,这是过去的经验了。Barcinski & Jeanjean 告诉我们:jpg效率低,用 flv 才是高效,而且文件量小。How could it be?

    OK,不知道大家是否有注意,在编码 flv 的时候可以设置关键帧距离。下图是AE里截的,Flash自带的编码器也可以设置。

    SNAG-000[2]

    一般我们都用自动方式,所以没太注意。但是如果将这个值设为1,那么就等于每一帧都编码为关键帧。由于播放器在解码非关键帧的时候需要在这一帧之前的关键帧数据,所以顺放和倒放的区别就在于:当前帧依赖的关键帧是否已经读取到内存中。那么如果每一帧都是关键帧,那顺放和倒放并没有区别!这样的设置无疑会增加 flv 的大小,但是还是比 jpg 序列小很多。而且在执行效率上,解码 flv 比 解码 jpg 速度快!感谢技术的进步,我们终于可以和臃肿的 jpg 序列说拜拜了!

    过去还有个经验是:先载小图,再载大图盖上去。但是在这个网站里并没有这种做法,对此他们的解释是:无法忍受freeze。因为大图片的解码过程会让 Flash Player卡住,通常情况下,用户不会注意到这瞬间的停顿。但是这里场景中结合了Papervision3D制作的纸,具有动态的物理效果,这样的停顿 就会很明显。因此他们采用直接加载最终精度的flv的办法。

    还记得IKEA网站中独特的加载方式吗?那是一种将序列重新组织的方法。可以让用户边下载边体验,没加载到的部分是过不去的。Barcinski & Jeanjean 面临同样的难题:即便用了flv压缩,主文件还是有16m之大。他们想了个天才的解决方法,在这篇文章里他们画了一个圆饼图表述了他们的思路。我总结一下:首先是在这个网站里达到平滑顺畅的全景体验需要144帧,如果我们隔一帧就抽掉一帧,就能省掉一半的文件量。此时播放的原始帧序号为“1,3,5,7,9,11,...”。如果我们再重复一次上一步的抽帧操作,那就只剩1/4的文件量了,已经降到的3M左右可以接受的范围。经过两次抽帧的文件只剩下36帧,此时播放的原始帧序号为“1,5,9,13,...”。抽帧后的视频仍然是一个完整的全景循环,只是不够平滑而已。

    方法出来了:我们先提供经过抽帧两次的视频,用户加载完这个文件已经可以正常的浏览网站。然后在后台继续加载第二次操作中抽去的那部分,当这个文件加载结束后,就已经还原了1/2的帧数。最后再把剩下的1/2——也就是所有的偶数帧组成的视频文件加载进来。

    非常酷的解决思路!我们团队立即给奔驰S网站重新开发了这部分功能。

    要实现它需要两步工作:一是制作出三个抽过帧的视频文件,二是开发一个播放逻辑。

    首先在AE中制作抽帧,手动操作显然不现实,我们的全景循环有300多帧!于是我找到了一个用Expression实现的办法。其实也很简单,用Time Remap重新映射就可以了,对应的表达式如下:

    • 视频文件1 : time*4
    • 视频文件2 : time*4+0.1
    • 视频文件3 : time*2+0.05

    由于time的单位是秒,我没找到将秒转换成帧数的方法。所以有了+0.1,+0.05这样奇怪的小数,其实换算过来就是+2帧和+1帧。表达式写好以后,要是不确定的话,拖动时间条看看重新计算过的时间码是否正确就可以了。

    接下来讲播放部分,最核心的是开发一个程序使得主时间轴的帧序号映射到三个视频文件中的对应帧。我们用set1_mc,set2_mc,set3_mc分别去加载三段视频。实现的代码如下:

    代码
    var setFrame;
    //判断当前帧对应哪一个视频文件,和对应哪一帧
    if (n%2) {
        
    //奇数帧分散在前两个文件中
        if (n%4 == 1) {
            currentSet 
    = set1_mc;
            setFrame 
    = (n+3)/4;
        } 
    else {
            currentSet 
    = set2_mc;
            setFrame 
    = (n+1)/4;
        }
    else {
        
    //偶数帧
        currentSet = set3_mc;
        setFrame 
    = n/2;
    }
    //如果对应的视频文件已经加载完成...
    if (currentSet.ready) {
        
    //其余的文件隐藏
        set1_mc._visible = false;
        set2_mc._visible 
    = false;
        set3_mc._visible 
    = false;
        currentSet.video.gotoAndStop(setFrame);
        currentSet._visible 
    = true;
    }

    最后为大家准备了这个网站的脱机版,有兴趣的自行下载研究下吧。感谢Barcinsk & Jeanjean和其他无私分享知识的人们,是他们让这个网络变得更加美好:)

  • 相关阅读:
    批处理(*.bat)文件 -> 命令
    设置柱状图:每项颜色不一样
    回到顶部 插件 遇到的一点小问题
    body的滚动事件的坑
    文章标题
    window.open()打开的新窗口被拦截的原因分析和解决方案
    常用正则表达式
    代码整洁之道,clean code
    表单序列化,获取Json对象
    利用聚合函数来去重
  • 原文地址:https://www.cnblogs.com/sevenyuan/p/1624700.html
Copyright © 2011-2022 走看看