专栏首页MixLab科技+设计实验室网易新闻《娱乐圈画传》H5的动画技巧

网易新闻《娱乐圈画传》H5的动画技巧

今天看到一个非常喜欢的H5,又是网易出品的!于是,我忍不住去研究了他的实现方式,有3个值得我们学习的地方,分别是逐帧动画,多种变换叠加的css动画,还有最亮的:画中画动画的实现方式,下文将分享技术实现方式。

实验环境,采用chrome开发者工具:

一、逐帧动画

这个h5,几乎没有采用gif图片,大部分采用css的方式实现的逐帧动画。

比如上图,每一帧的尺寸是500px 1000px,共有8帧,存成雪碧图的形式。

CSS雪碧 即CSS Sprite,也有人叫它CSS精灵,是一种CSS图像合并技术,该方法是将小图标和背景图像合并到一张图片上,然后利用css的背景定位来显示需要显示的图片部分。好处是减少你的网站的HTTP请求数量。

重点在于这句代码 animation: people_ani 1s steps(1,end) infinite;

其他如下:

<div class="people"></div>

.people { 
    animation: people_ani 1s steps(1,end) infinite; 
    background: url(images/cover_people.png) no-repeat;
    position: absolute;
    left: 20px;
    bottom: -4px;
    width: 500px;
    height: 1000px;
}
@keyframes people_ani {
    0%{background-position:0 0}
    12.5%{background-position:-500px 0}
    25%{background-position:-1000px 0}
    37.5%{background-position:-1500px 0}
    50%{background-position:0 -1000px}
    62.5%{background-position:-500px -1000px}
    75%{background-position:-1000px -1000px}
    87.5%{background-position:-1500px -1000px}
    100%{background-position:-2000px -1000px}
}

二、多种变换叠加的动画

首页的海浪波动动画,在x轴跟y轴都同时运动,采用了伪元素的这种方法。

x轴的变化写在元素本身,y轴的变化写在before里。

代码如下:

<div class="water1"></div>


.water1 { 
    position: absolute; 
    left: 470px; 
    top: 760px;
    width: 350px;
    height: 400px; 
}

.water1 {
    animation: water1 3.0s ease 1s infinite;
}

@keyframes water1{
    0%{transform:translate(0,0)}
    50%{transform:translate(-60px,0)}
    100%{transform:translate(0,0)}
}

.water1:before {
    content: "";
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    background: url(images/sprite_v2.png) no-repeat 0 -690px;
}

.water1:before {
    animation: water2 3.0s ease 2s infinite;
}
@keyframes water2{
    0{transform:translate(0,0)}
    50%{transform:translate(0,-50px)}
    ‍00%{transform:translate(0,0)}
}

三、动态部分与背景分离: 这种就不多说了,这样可以减少图片文件大小。

四、画中画的实现:

整个h5最吸引人的就是画中画的动画形式,下图是前后2帧的图片:

前后2帧的变化关系如下图所示:

这里都是采用canvas逐帧绘制而成的,比css方案有个好处,就是同一时间绘制显示的内容,避免了采用css分别变换带来的不确定性。

我们尝试下,这里只选取了其中2帧作为演示。

html代码:

<canvas id="app" width="750" height="1206"></canvas>

<div class="collection">
    <img src="./cover_v2.jpg">
    <img src="./p1.jpg"">
    <img src="./p2.jpg">
</div>

canvas撑满屏幕,div class='collection'隐藏。

设一个初始化参数: js代码:

    domList=document.querySelector('.collection').children;
    imgList= [{
          link: "./cover_v2.jpg",
          imgW: "750",
          imgH: "1206"
      }, {
          link: "./p1.jpg",
          imgW: "1875",
          imgH: "3015",
          areaW: "152",
          areaH: "244",
          areaL: "370",
          areaT: "1068",
          gif: "p1"
      }, {
          link: "./p2.jpg",
          imgW: "1875",
          imgH: "3015",
          areaW: "556",
          areaH: "894",
          areaL: "1251",
          areaT: "1050"
      }];
    
    
    index=1;
    radio=1;
        
    imgNext ={
          link: "./p2.jpg",
          imgW: "1875",
          imgH: "3015",
          areaW: "556",
          areaH: "894",
          areaL: "1251",
          areaT: "1050"
      };

    imgCur ={
          link: "./p1.jpg",
          imgW: "1875",
          imgH: "3015",
          areaW: "152",
          areaH: "244",
          areaL: "370",
          areaT: "1068",
          gif: "p1"
      };
    
    //p2.jpg
    img_oversize = domList[index + 1];
    
    //p1.jpg
    img_minisize = domList[index];    

当长按start按钮时,开始绘制逐帧动画,是通过radio不断乘于一个缩放系数达到目的的。

radio=0.99*radio

重复这一过程的代码如下:

radio=0.99*radio
drawImgOversize(img_oversize, imgNext.imgW, imgNext.imgH, imgNext.areaW, imgNext.areaH, imgNext.areaL, imgNext.areaT, radio)

上面这个代码表示,把后面一帧逐渐缩小至手机屏幕,原理如下图:

再把前面一帧,逐渐缩小,成为画中画,原理如下图:

代码:

radio=0.99*radio
drawImgMinisize(img_minisize, imgCur.imgW, imgCur.imgH, imgNext.imgW, imgNext.imgH, imgNext.areaW, imgNext.areaH, imgNext.areaL, imgNext.areaT, radio)

为了实验方便,我把radio跟两个方法都拆开来了,实际使用的时候,只需调用一次radio=0.99*radio即可。

drawImgOversize与drawImgMinisize有兴趣再深入理解下哦,代码如下:

   function drawImgOversize(img, imgNextWidth,imgNextHeight,imgNextAreaWidth, imgNextAreaHeight, imgNextAreaL, imgNextAreaT, radio) {
       
       var sx = imgNextAreaL - (imgNextAreaWidth / radio - imgNextAreaWidth) * (imgNextAreaL / (imgNextWidth - imgNextAreaWidth)),
            sy = imgNextAreaT - (imgNextAreaHeight / radio - imgNextAreaHeight) * (imgNextAreaT / (imgNextHeight - imgNextAreaHeight)),
            swidth = imgNextAreaWidth / radio,
            sheight = imgNextAreaHeight / radio,
            x = 0,
            y = 0,
            width = 750,
            height = 1206; 
      
      var   c=document.querySelector('#app')
      var  ctx=c.getContext('2d');

      ctx.drawImage(img, sx, sy, swidth, sheight, x, y, width, height);

    }; 
      
    
    function drawImgMinisize(img, imgCurWidth, imgCurHeight, imgNextWidth, imgNextHeight, imgNextAreaW, imgNextAreaH, imgNextAreaL, imgNextAreaT, radio) {
        var  c=document.querySelector('#app')
        var  ctx=c.getContext('2d');
        var sx = 0,
            ‍s‍y = 0,
            swidth = imgCurWidth,
            sheight = imgCurHeight,
            x = (imgNextAreaW / radio - imgNextAreaW) * (imgNextAreaL / (imgNextWidth - imgNextAreaW)) * radio * 750 / imgNextAreaW,
            y = (imgNextAreaH / radio - imgNextAreaH) * (imgNextAreaT / (imgNextHeight - imgNextAreaH)) * radio * 1206 / imgNextAreaH,
            width = 750 * radio,
            height = 1206 * radio;

      ctx.drawImage(img, sx, sy, swidth, sheight, x, y, width, height);

    };

以上就是动画技术的核心内容,以供学习研究之用。

附上h5的地址:

http://ent.163.com/special/entphotos2017/

ps:

之前我也研究另外2个喜欢的h5的实现方式,比如:

全民刷军装背后的AI技术及简单实现 从网易《初心》H5里学到的一些

本文分享自微信公众号 - 科技Mix设计Lab(Design-AI-Lab),作者:shadow

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-12-29

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 设计师会编程、程序员懂艺术:Semi Flat Design

    本公众号定期更新关于 设计师、程序员发挥创意 互相融合的指南、作品。 主要技术栈: nodejs、react native、electron 本号正在更新的系列...

    mixlab
  • 人人都是超级设计师@人工智能服装设计

    最近有了darksee.ai的帮助,行业的动态了如指掌,今天总结一下服装设计领域的人工智能新的动态。通过本文可以了解什么是超级设计师?如何成为超级设计师?

    mixlab
  • 为什么不喜欢人工智能建筑设计?

    这是mixlab社区成员ML403 理策 对于 「 当下的计算机介入设计」 的一些观点,以下时间交给他。

    mixlab
  • 第3天:CSS浮动、定位、表格、表单总结

    今天学的是浮动、定位、表格、表单等内容,这些是CSS中最容易混淆的知识,有许多小技巧在写代码过程中需要注意。下面是主要知识点:

    半指温柔乐
  • 【二叉树打卡4】二叉树的中序遍历(非递归版)

    二叉树的中序遍历顺序是左-根-右。我们可以采用一个栈来辅助,我们把中序遍历的结果放到一个 ArrayList 容器中作为返回值,具体步骤如下:

    帅地
  • PriorityQueue 源码分析

    tomas家的小拨浪鼓
  • zookeeper编程02-服务器上下线动态感知

    NameNode判断DataNode是否下线的时间太长了,利用zookeeper实现服务器上下线动态感知

    CoderJed
  • TypeScript中的怪语法

    绿巨人
  • A3C原理和代码解析

    完整代码地址:https://github.com/dgriff777/a3c_continuous

    用户1908973
  • TypeScript中的怪语法

    绿巨人

扫码关注云+社区

领取腾讯云代金券