大家好,咱们是明源云前端团队。

家喻户晓,B 站 是个适宜学习的好网站,咱们团队的小伙伴也是常常上 B站 学习。

某一天在 B站 学习的时候,发现 B站 曾经开启了秋季主题,并且在头图的这个交互上还内有乾坤。随着咱们的鼠标变换位置,头图也跟随着咱们的鼠标地位进行变换,配上秋季主题,显得特地治愈。(如下图)

小编对这个交互也是挺感兴趣的,那接下来咱们间接进入主题,来试着实现这种动画成果吧!

原理剖析

咱们先进行实现原理剖析,关上控制台,能够发现这个成果是通过几个图层变换位置和高斯含糊来实现的(如下图)

除此之外,还有个小女孩的 眨眼 特效,是通过切换图片来实现的。所以咱们实现的步骤合成为四步:

  1. 获取对应的图片;
  2. 将图片依照效果图,摆放在对应的地位,设置默认的高斯含糊;
  3. 通过切换图片制作 眨眼 特效;
  4. 依据鼠标地位切换图片地位和高斯含糊;

那咱们遵循下面的步骤,开始制作吧!

获取图片

首先,咱们关上控制台(F12),在控制台输出上面这行代码来获取图片。

var images = document.querySelectorAll(".animated-banner .layer img");var urlList = [].slice.call(images).map((item) => item.src);console.log(JSON.stringify(urlList, null, 2));

如上图所示,咱们将这几张图片下载到本人的电脑中(如下图)

还有个动画轮播图,咱们应用上面这行代码来获取不同的几张图片。

var animateImgList = [];setInterval(() => {  var imgSrc = document.querySelector(    ".animated-banner >.layer:nth-child(2) img"  ).src;  if (!animateImgList.includes(imgSrc)) {    console.log(imgSrc);    animateImgList.push(imgSrc);  }}, 200);

如上图所示,咱们能够失去几张不同状态的图片,咱们下载到本人的电脑里即可。

摆放图片

咱们下载的几张图片都是 png 格局的,咱们能够应用定位将其重叠到一起。

间接新建一个 index.html,填充内容如下:

<!DOCTYPE html><html lang="en">  <head>    <meta charset="UTF-8" />    <meta name="viewport" content="width=device-width,initial-scale=1.0" />    <title>Document</title>  </head>  <style>    * {      margin: 0;      padding: 0;    }    .img-list {      width: 100%;      min-width: 1000px;      height: 155px;      position: relative;      overflow: hidden;    }    .img-list .layer {      position: absolute;      left: 0;      top: 0;      width: 100%;      height: 100%;      display: flex;      align-items: center;      justify-content: center;    }  </style>  <body>    <section class="img-list">      <div class="layer">        ![](./assets/1.png)      </div>      <div class="layer">        ![](./assets/2_1.png)      </div>      <div class="layer">        ![](./assets/3.png)      </div>      <div class="layer">        ![](./assets/4.png)      </div>      <div class="layer">        ![](./assets/5.png)      </div>      <div class="layer">        ![](./assets/6.png)      </div>    </section>  </body></html>

下面做了简略的图片排列,实现的成果如下图所示:

从上图能够看出,咱们将多张图片重叠后,曾经有初步的雏形了,接下来咱们来设置默认的高斯含糊吧。

因为咱们的地位偏移和高斯含糊在前面须要波及到交互,所以咱们间接应用 JS 进行设置,这里咱们借助一下 Jquery,在 body 后引入 jquery,而后写入咱们的 javascript 脚本(如下)。

<script src="https://cdn.bootcdn.net/ajax/libs/jquery/1.10.0/jquery.js"></script><script>  const imgList = $(".img-list .layer img");  // 默认的地位偏移与高斯含糊值  const defaultStyles = [    { translateX: 0, translateY: 0, blur: 4 },    { translateX: 0, translateY: 0, blur: 0 },    { translateX: -50, translateY: 0, blur: 1 },    { translateX: 0, translateY: 4.2, blur: 4 },    { translateX: 0, translateY: -1.8, blur: 5 },    { translateX: 0, translateY: 0, blur: 6 },  ];  function setDefaultImgStyle() {    for (let i = 0; i < imgList.length; i++) {      const imgItem = imgList[i];      const defaultStyle = defaultStyles[i];      const { translateX, translateY, blur } = defaultStyle;      // 设置地位偏移以及高斯含糊      $(imgItem).css({        // 地位偏移        transform: `translate(${translateX}px, ${translateY}px)`,        // 高斯含糊        filter: `blur(${blur}px)`,      });    }  }  setDefaultImgStyle();</script>

在设置好了地位偏移和高斯含糊后,咱们的动态页面曾经和效果图完全一致了(如下图)。

制作眨眼特效

咱们的动态页面曾经制作的差不多了,接下来咱们来用 JS 简略实现 眨眼 特效吧。

这个比较简单,咱们只须要设置一个定时器,每 3 秒切换一次图片集即可,代码实现如下:

function setShakeAnimation() {  // 第二张小女孩图片  const imgGirl = $(".img-list .layer:nth-child(2) img");  // 每 3 秒眨一次眼睛  setInterval(() => {    // 半闭眼    $(imgGirl).attr("src", "./assets/2_2.png");    // 100 毫秒后齐全闭上眼眼睛    setTimeout(() => {      $(imgGirl).attr("src", "./assets/2_3.png");    }, 100);    // 300 毫秒后半睁开眼睛    setTimeout(() => {      $(imgGirl).attr("src", "./assets/2_2.png");    }, 300);    // 400 毫秒后齐全睁开眼睛    setTimeout(() => {      $(imgGirl).attr("src", "./assets/2_1.png");    }, 400);  }, 3000);}setShakeAnimation();

而后,咱们来看看咱们的 眨眼 特效吧!(如下图)

如上图所示,咱们的 眨眼 特效曾经能够做到以假乱真啦!

动静交互

最初,咱们来为咱们的图层合集增加上交互成果吧!

咱们从 B站 原有的交互中能够发现,当咱们把鼠标放上去左右挪动时,图片产生了地位和高斯含糊度的变动。所以咱们先把鼠标挪动的事件监听加上,代码实现如下:

// 屏幕宽度const width = document.body.clientWidth;// 鼠标进入的事件$(".img-list").mouseenter((e) => {  // 鼠标来到时解除事件监听,并重置状态  $(".img-list").mouseleave(() => {    setDefaultImgStyle();    $(".img-list").off("mousemove");    $(".img-list").off("mouseleave");  });  // 鼠标进入时记录地位  const originalX = e.pageX;  $(".img-list").mousemove((e) => {    // 鼠标挪动时记录地位    const currentX = e.pageX;    // 依据屏幕宽度和挪动间隔,计算挪动的比例    const offsetRatio = (currentX - originalX) / width;    // 鼠标左移    if (offsetRatio < 0) {      setLeftImgStyle(Math.abs(offsetRatio));      // 鼠标右移    } else {      setRightImgStyle(offsetRatio);    }  });});

接下来,咱们通过大抵测量一下后会发现,高斯含糊变动的成果如下表所示。

图片序号初始值(高斯含糊值)从最右侧到最左侧(高斯含糊值)从最左侧到最右侧(高斯含糊值)
144 -> 04 -> 8
200 -> 100 -> 8
311 -> 51 -> 4
444 -> 134 -> 0 -> 4
555 -> 145 -> 0 -> 4
666 -> 126 -> 0

地位变动的成果如下表所示。

图片序号初始值(X 轴地位)从最右侧到最左侧(X 轴地位)从最左侧到最右侧(X 轴地位)
1000
20-99
3-50-8021
40-3635
50-7877
60-9796

依据下面两张表,咱们就能够开始写代码啦,代码实现如下:

// 鼠标左移后的最终目标地位const leftStyles = [  {    translateX: 0,    translateY: 0,    blur: 0,  },  {    translateX: -9,    translateY: 0,    blur: 10,  },  {    translateX: -80,    translateY: 0,    blur: 5,  },  {    translateX: -36,    translateY: 4.2,    blur: 13,  },  {    translateX: -78,    translateY: -1.8,    blur: 14,  },  {    translateX: -97,    translateY: 0,    blur: 12,  },];function setLeftImgStyle(offsetRatio) {  for (let i = 0; i < imgList.length; i++) {    const imgItem = imgList[i];    const {      translateX: defaultTranslateX,      translateY: defaultTranslateY,      blur: defaultBlur,    } = defaultStyles[i];    const leftStyle = leftStyles[i];    // 依据挪动比例计算最终坐标和高斯含糊值    const translateX =      (leftStyle.translateX - defaultTranslateX) * offsetRatio +      defaultTranslateX;    const blur = (leftStyle.blur - defaultBlur) * offsetRatio + defaultBlur;    // 设置地位偏移以及高斯含糊    $(imgItem).css({      // 地位偏移      transform: `translate(${translateX}px, ${defaultTranslateY}px)`,      // 高斯含糊      filter: `blur(${blur}px)`,    });  }}// 鼠标右移后的最终目标地位const rightStyles = [  {    translateX: 0,    translateY: 0,    blur: 8,  },  {    translateX: 9,    translateY: 0,    blur: 8,  },  {    translateX: 21,    translateY: 0,    blur: 4,  },  {    translateX: 35,    translateY: 4.2,    blur: [0, 4],  },  {    translateX: 77,    translateY: -1.8,    blur: [0, 4],  },  {    translateX: 96,    translateY: 0,    blur: 0,  },];function setRightImgStyle(offsetRatio) {  for (let i = 0; i < imgList.length; i++) {    const imgItem = imgList[i];    const {      translateX: defaultTranslateX,      translateY: defaultTranslateY,      blur: defaultBlur,    } = defaultStyles[i];    const rightStyle = rightStyles[i];    let rightBlur = rightStyle.blur;    let blur = defaultBlur;    // 依据挪动比例计算最终坐标和高斯含糊值    const translateX =      (rightStyle.translateX - defaultTranslateX) * offsetRatio +      defaultTranslateX;    if (Array.isArray(rightBlur)) {      const targetBlur = offsetRatio < 0.5 ? rightBlur[0] : rightBlur[1];      const ratio =        offsetRatio < 0.5 ? offsetRatio * 2 : (offsetRatio - 0.5) * 2;      const currentBlur = offsetRatio < 0.5 ? defaultBlur : rightBlur[0];      blur = (targetBlur - currentBlur) * ratio + currentBlur;    } else {      blur = (rightBlur - defaultBlur) * offsetRatio + defaultBlur;    }    // 设置地位偏移以及高斯含糊    $(imgItem).css({      // 地位偏移      transform: `translate(${translateX}px, ${defaultTranslateY}px)`,      // 高斯含糊      filter: `blur(${blur}px)`,    });  }}

在下面的代码实现中,咱们在鼠标左移右移的过程中增加了图片地位偏移与高斯含糊值,最初咱们实现的成果就和 B站 的原版很相近了!(如下图)

好了,功败垂成啦!

总结

通过简略的步骤剖析,咱们将几张图片组合起来就模拟出了 B站 的秋季主题成果啦!

这个案例是在某次学习(发愣)的时候发现 B站 的秋季主题挺有意思的,这里分享进去给大家,用几张图片组合出这么一个创意交互,也是挺乏味的~

求贤若渴

明源云链前端团队是个充斥激情的团队,明源云也是对技术非常重视的公司。

咱们有欠缺的福利:六险一金 +(丰富)年终奖 + 带薪休假 + 通信补贴

咱们的工作气氛:弹性工作,扁平构造,崇尚以解决问题为外围、简略高效的互联网文化,激励技术创新分享,每年举办黑客马拉松(最高奖 3W 奖金)、极客大赛、挪动社群等技术性赛事

咱们有人文关心:花式下午茶(每周都有)、生日礼金、收费游览、流动经费、结婚礼金、收费体检

咱们还有丰盛的业余社团活动:篮球、足球、瑜伽、羽毛球、台球、棋牌赛

咱们招聘的岗位有:(中高级)前端工程师(中高级)测试工程师(中高级)Java 工程师(中高级)PHP 工程师

Base:深圳武汉

欢送投递简历到邮箱 lit31@mingyuanyun.com,或者增加上面微信备注 明源云 进行征询吧!