手摸手带你复刻B站banner图【收藏下次换主题直接用】

凉蟾光满。桂子飘香远。 ------ 宋.谢逸 《点绛唇·金气秋分》

写在前面

最后有源码,可以先去下下来跑起来再看文章的细分,再决定看哪一部分,或许更好。一直认为有时候项目先跑起来,再去联想自己哪一部分比较模糊再具体去看,熟悉的就可看可不看。下一个vscode插件live-server去本地跑起来。

目录

  • Banner目录搭建与素材的获取

  • Banner数据结构约定与使用

  • Banner元素DOM的属性编写

  • Banner页面鼠标事件&视觉差交互效果

内容

01. Banner目录搭建与素材的获取

根据控制台的元素可看出,是相同的class为layer的div循环把素材循环有规律地放在指定位置,通过设置元素的transformtranslate的x、y坐标来逐个把每个元素组成一幅会动的画,拆解成如下:

html 复制代码
  <div class="header-banner">
    <div class="animated-banner">
        // ...
        // 🎨 这里循环放每个素材,汇成一幅画
    </div>
  </div>
css 复制代码
body {
  margin: 0;
  padding: 0;
}
.header-banner {
  position: relative;
  z-index: 0;
  min-height: 155px;
  height: 9.375vw;
  max-height: 240px;
  background-color: #e3e5e7;
}
.animated-banner {
  position: absolute;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  overflow: hidden;
}
.layer {
  position: absolute;
  left: 0;
  top: 0;
  height: 100%;
  width: 100%;
  display: flex;
  align-items: center;
  justify-content: center;
}

打底底色框架效果:

这里值得注意的是,视频用了webm,也就是下面👇两个视频。

记得设置mutedtrue、looptrue、autoplaytrue和style.objectFit = "cover",如下图。

02. Banner数据结构约定与使用

首先在index.html文件里面全局搜索split_layer这个单词,不需要用site_sucker去爬取页面或者保存当前页面,只需要打开控制台找Elements那一栏,直接全部复制到一个sublime页面,去全局找就好:

得到的split_layer这个东西是这样的:

打开console那一栏:

  • 赋值一个JSON.parse(xx)的值给a
  • 然后copy(a),就可以在粘贴板上有这个数据对象了。(这个对象大有作用,因为我们基本不用看位置偏移诸如此类的配置项)

由于太大了,我只用截图来展示,如下:

arduino 复制代码
const layers = {
    version: "1",
    layers: [
        // ... 这里就是一个个小图对象
    ]
}

我们这里的话定义一个layers承载这些数据。至于一个个素材的话,我们自己去下载下来,放在static文件夹里。

主要代码: 通过循环这个layers数据(这个layers数据定义了资源路径scaleinitialrotatetranslatebluropacityname等等初始数据),判断是视频的话就创建video,如果是图片就创建img

js 复制代码
layers.map((layer) => {
    layer.resources.map((resource, resourceKey) => {
        
      if (!/\.(webm|mp4)$/.test(resource.src)) {

             // 🎨 创建图片
             const imgElement = document.createElement('img')
             imgElement.src = resource.src
             layer.resources[resourceKey].el = imgElement

      } else {

            // 🎨 创建视频
            const videoElement = document.createElement('video')
            videoElement.muted = !0,
            videoElement.loop = !0,
            videoElement.autoplay = !0,
            videoElement.src = resource.src,
            videoElement.playsInline = !0,
            videoElement.style.objectFit = 'cover',
            layer.resources[resourceKey].el = videoElement

      }
    })
});

03. Banner元素DOM的属性编写

把各个图片的元素位置设置谁给你初始的偏移值,来调整它们本身应该待的位置。

我们观察一下B站首页控制台对应的每一个layer元素的dom结果,会发现处理了**一些style的属性值,一些width、height、translate(平移)、rotate(旋转)、scale(缩放)、opacity(透明度)**等等一些属性。

这里值得一提的是video的宽高的获取。

video宽高的获取,我们这里用了eachElement.addEventListener('loadedmetadata', () => { // ... })这个方法来获取。从而再把视频的宽高给赋值上去。

得到的效果如下图:

04. Banner页面鼠标事件&视觉差交互效果

运用requestAnimationFrame告诉浏览器我们要执行动画,并且要求浏览器再下次重绘之前调用指定的回调函数,更新动画。执行次数通常是每秒60次。不用了就把动画cancel掉。

requestAnimationFrame

在过去,我们执行动画一般用setTimeout或者setInterval去创建动画效果。但是这些方法存在一些问题。

setTimeout和setInterval固定了动画的时间间隔,没有考虑到浏览器的刷新频率。可能导致动画在某些情况下出现撕裂、卡顿或者不连贯的问题

requestAnimationFrame就可以解决这个问题,它接受一个回调函数作为参数,这个回调函数会在下次浏览器刷新时调用。也就意味着动画会跟浏览器的帧之间进行同步。

js 复制代码
  document.addEventListener("mouseleave", mouseLeaveFn), // 执行鼠标离开事件
  window.addEventListener("mousemove", mouseMoveFn) // 执行鼠标移动时间
  window.addEventListener("resize", resizeFn) // 根据浏览器窗口大小变化执行相应事件

最终效果:

源码地址

下次b站再换主题,你就去谷歌控制台去找素材,然后下到本地(主要是做了防盗链处理),下到本地也可以积累一季一季的素材,然后换layers数据结构即可(这个去项目中的index.html)里面去找就可以了(上面有讲)。

总结

最终,话不多说,如果想下次有换主题,只需要需要layers这个数据(也就是一个一个元素的一些相关属性数据的大对象数组)即可!

祝您开发有乐趣。

☎️ 希望对大家有所帮助,如有错误,望不吝赐教,欢迎评论区留言互相学习。

相关推荐
还是大剑师兰特38 分钟前
D3的竞品有哪些,D3的优势,D3和echarts的对比
前端·javascript·echarts
王解38 分钟前
【深度解析】CSS工程化全攻略(1)
前端·css
一只小白菜~1 小时前
web浏览器环境下使用window.open()打开PDF文件不是预览,而是下载文件?
前端·javascript·pdf·windowopen预览pdf
方才coding1 小时前
1小时构建Vue3知识体系之vue的生命周期函数
前端·javascript·vue.js
阿征学IT1 小时前
vue过滤器初步使用
前端·javascript·vue.js
王哲晓1 小时前
第四十五章 Vue之Vuex模块化创建(module)
前端·javascript·vue.js
丶21361 小时前
【WEB】深入理解 CORS(跨域资源共享):原理、配置与常见问题
前端·架构·web
发现你走远了1 小时前
『VUE』25. 组件事件与v-model(详细图文注释)
前端·javascript·vue.js
Mr.咕咕1 小时前
Django 搭建数据管理web——商品管理
前端·python·django
张张打怪兽1 小时前
css-50 Projects in 50 Days(3)
前端·css