B站的前端样式一直是我学习和模仿的对象,特别是它的首页头部动画,可以随着鼠标的移动进行场景的变化,很酷,所以我对它进行了大体上的模仿
废话不多说,先看效果

仿B站首页动画演示

视频打不开点击这里

完整代码如下:这里将css、js、html代码整合到一块去了,大家也可以去码云自行下载
码云地址

<!DOCTYPE html>
<html lang="en">
<head><meta charset="UTF-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>Document</title><style>* {margin: 0;padding: 0;}.bili-banner {margin: 0 auto;position: relative;z-index: 0;min-height: 155px;height: 9.375vw;min-width: 999px;background-color: pink;display: flex;justify-content: center;background-repeat: no-repeat;background-position: center 0;background-size: cover;}.animateds-banner {position: absolute;top: 0;bottom: 0;left: 0;right: 0;overflow: hidden;}.animateds-banner > .layer {position: absolute;left: 0;top: 0;height: 100%;width: 100%;display: flex;align-items: center;justify-content: center;}</style>
</head>
<body><!-- 1.多图层组合的静态页面2.不同图层具有不同的清晰度第六张图片:从初始位置鼠标右移,opacity从0增加(不一定到1,这与初始位置在屏幕的位置有关),左移保持0不变第九、十张图片:从初始位置鼠标左移移,opacity从0增加(不一定到1,这与初始位置在屏幕的位置有关),右移保持0不变左移offset大于0,右移offset小于03.鼠标移动导致清晰度变化(渐变效果)4.鼠标移动导致左右跟随5.鼠标离开,效果还原--><div class="bili-banner"><div class="animateds-banner"><div class="layer"><img src="img/1.png" height="184" data-height="360" data-width="9666" width="4957"  /></div><div class="layer"><img src="img/2.png" height="184" data-height="360" data-width="9666" width="4957"  /></div><div class="layer"><img src="img/3.png" height="166" data-height="360" data-width="3523" width="1626" /></div><div class="layer"><img src="img/4.png" height="180" data-height="360" data-width="2938" width="1476"  /></div><div class="layer"><img src="img/5.png" height="64" data-height="139" data-width="556" width="256"  /></div><div class="layer"><img src="img/6.png" height="86" data-height="302" data-width="734" width="210"  /></div><div class="layer"><img src="img/7.png" height="129" data-height="180" data-width="1757" width="1261"  /></div><div class="layer"><img src="img/8.png" height="83" data-height="116" data-width="1757" width="1261"  /></div><div class="layer"><img src="img/9.png" height="141" data-height="346" data-width="497" width="203"  /></div><div class="layer"><img src="img/10.png" height="105" data-height="256" data-width="146" width="59"  /></div><div class="layer"><img src="img/11.png" height="117" data-height="254" data-width="602" width="277" /></div><div class="layer"><img src="img/12.png" height="184" data-height="360" data-width="4277" width="2193"  /></div><div class="layer"><img src="img/13.png" height="150" data-height="327" data-width="933" width="430"  /></div><div class="layer"><img src="img/14.png" height="217" data-height="353" data-width="740" width="455"  /></div><div class="layer"><img src="img/15.png" height="184" data-height="360" data-width="1916" width="982"  /></div><canvas width="1677" height="159"style="position: absolute; top: 0px; left: 0px;"></canvas></div></div><script>let banner = document.querySelector('.animateds-banner')// 获取到所有的图层,也就是包裹在img外的所有divlet layers = document.querySelectorAll('.layer')let layers_data = [{ translateX: 0, translateY: -15.3871, filter_blur: 0, opacity: 1},{ translateX: 1128.39, translateY: 0, filter_blur: 0, opacity: 1},{ translateX: 692.419, translateY: 0, filter_blur: 0, opacity: 1},{ translateX: -653.439, translateY: 0, filter_blur: 0, opacity: 1},{ translateX: 623.177, translateY: 46.1613, filter_blur: 0, opacity: 1},{ translateX: 258.503, translateY: 37.3394, filter_blur: 0, opacity: 0},{ translateX: 114.89, translateY: 14.3613, filter_blur: 0, opacity: 1},{ translateX: -359.032, translateY: 50.2645, filter_blur: 0, opacity: 1},{ translateX: -246.194, translateY: 16.4129, filter_blur: 0, opacity: 0},{ translateX: -348.774, translateY: 32.8258, filter_blur: 0, opacity: 0},{ translateX: -92.3226, translateY: 13.8484, filter_blur: 0, opacity: 1},{ translateX: 102.581, translateY: 0, filter_blur: 0, opacity: 1},{ translateX: 221.574, translateY: 13.8484, filter_blur: 0, opacity: 1},{ translateX: 2154.19, translateY: 0, filter_blur: 2, opacity: 1},{ translateX: -1025.81, translateY: 0, filter_blur: 1, opacity: 1},]// 初始化所有的图层let init = function() {for (const k in layers) {if (Object.hasOwnProperty.call(layers, k)) {// 获取到当前图层(div),其中k是索引// console.log(k);const element = layers[k]// 获取到当前图层所需要的数据let element_data = layers_data[k]element.children[0].style = 'transform: scale(1) translate('+ element_data.translateX +'px,'+ element_data.translateY +'px) rotate(0deg); filter: blur('+ element_data.filter_blur +'px); opacity:'+ element_data.opacity +';'// 第二种方式:模板字符串// element.children[0].style = `transform: scale(1)//                              translate( ${element_data.translateX}px, ${element_data.translateY}px )//                              rotate(0deg);//                              filter: blur(${element_data.filter_blur});//                              opcatity: ${element_data.opacity};//                              `}}}let x_first = 0let x_now = 0let x_offset = 0// 鼠标悬浮,记录鼠标第一次到banner的位置x_firstbanner.addEventListener("mouseover", function(e) {x_first = e.clientX// console.log(x_first);})// 鼠标移动banner.addEventListener("mousemove", function(e) {// 鼠标移动的当前位置x_now = e.clientX// 在观察B站的规律后,发现:// 鼠标移动到该banner的位置,此处为初始位置,在接下来的鼠标移动位置过程中,translate的值的改变都是基于这个点的,// 而x_offset = x_first - x_now正好将这个问题包裹进去,x_first就是该初始位置,translate的值也就是根据x_offset来变的x_offset = x_first - x_now// 每个图片都要根据x_offset移动响应的距离for (const k in layers) {if (Object.hasOwnProperty.call(layers, k)) {let level = (15 - parseInt(k)) * 0.5;// 获取当前图层const element = layers[k]// 获取初始化图层数据,以便在此基础上进行改变const element_data = layers_data[k]let new_translateX = element_data.translateX + x_offset / levellet new_opacity = element_data.opacityif (k == 5 && x_offset < 0) {new_opacity = 0.333} else if ((k == 8 || k == 9) && x_offset > 0) {new_opacity = 0.44} else {new_opacity = element_data.opacity}element.children[0].style = `transform: scale(1) translate(${new_translateX}px,${element_data.translateY}px ) rotate(0deg);filter: blur(${element_data.filter_blur}px);opacity:${new_opacity};`}}})// 鼠标移出,恢复到默认位置banner.addEventListener("mouseout", function() {init()})window.onload = function() {init()}</script>
</body>
</html>

我就在这里讲讲我的思路吧,因为效果也不是完全一致的,就说一下在写代码过程中遇到的一些问题

  1. 首先,我先看的B站源代码,没有找到控制该效果的js文件,所以就先将其html框架copy下来了,当然,它的样式是这样的
    我的代码在它的基础上将img标签中的内联样式进行了提取,至于为什么要这样做,一会会说明,css样式是一样的,就直接copy引入即可
  2. 去B站首页观察这个效果和它的源代码的时候,我发现了以下几点:首先,这一张一张的图片的移动速度肯定是不相同的,第二,在我鼠标移动进去这个区域的时候,图片的translate的值是不变的,也就是说,鼠标第一次进入这个区域的时候,这个位置就是移动的初始位置,移动过程中,改变相应速率的translate的值,第三,鼠标移出以后,恢复到原来的状态
  3. 有了以上信息,就开始着手做了,首先,为了将所有的图片组合成一个静态页面,就免不了对图片的tanslate的值进行相应的改变,有的图片改变X,有的图片同时改变X和Y,而鼠标移动的过程,只需要改变translateX的值就行,所以将img的内联样式提取出来成为一个对象数组,这样读取很简单,因为初始化的数据只在一开始呈现页面时使用
let layers_data = [{ translateX: 0, translateY: -15.3871, filter_blur: 0, opacity: 1},{ translateX: 1128.39, translateY: 0, filter_blur: 0, opacity: 1},{ translateX: 692.419, translateY: 0, filter_blur: 0, opacity: 1},{ translateX: -653.439, translateY: 0, filter_blur: 0, opacity: 1},{ translateX: 623.177, translateY: 46.1613, filter_blur: 0, opacity: 1},{ translateX: 258.503, translateY: 37.3394, filter_blur: 0, opacity: 0},{ translateX: 114.89, translateY: 14.3613, filter_blur: 0, opacity: 1},{ translateX: -359.032, translateY: 50.2645, filter_blur: 0, opacity: 1},{ translateX: -246.194, translateY: 16.4129, filter_blur: 0, opacity: 0},{ translateX: -348.774, translateY: 32.8258, filter_blur: 0, opacity: 0},{ translateX: -92.3226, translateY: 13.8484, filter_blur: 0, opacity: 1},{ translateX: 102.581, translateY: 0, filter_blur: 0, opacity: 1},{ translateX: 221.574, translateY: 13.8484, filter_blur: 0, opacity: 1},{ translateX: 2154.19, translateY: 0, filter_blur: 2, opacity: 1},{ translateX: -1025.81, translateY: 0, filter_blur: 1, opacity: 1},
]

4.给每一个图层,也就是每个img标签赋值(for in循环)就可以得到所有图层结合的静态页面,我将这个过程封装到了初始化函数中,因为鼠标移开效果复原也是相同的操作,所以直接调用init函数即可,同时注意在给样式重新赋值的时候,有两种写法,我个人比较喜欢模板字符串,支持换行,然后数据拼接也比较简洁易懂,鼠标移出,恢复原状,那么也调用一次init函数

// 初始化所有的图层
let init = function() {for (const k in layers) {if (Object.hasOwnProperty.call(layers, k)) {// 获取到当前图层(div),其中k是索引// console.log(k);const element = layers[k]// 获取到当前图层所需要的数据let element_data = layers_data[k]element.children[0].style = 'transform: scale(1) translate('+ element_data.translateX +'px,'+ element_data.translateY +'px) rotate(0deg); filter: blur('+ element_data.filter_blur +'px); opacity:'+ element_data.opacity +';'// 第二种方式:模板字符串// element.children[0].style = `transform: scale(1)//                              translate( ${element_data.translateX}px, ${element_data.translateY}px )//                              rotate(0deg);//                              filter: blur(${element_data.filter_blur});//                              opcatity: ${element_data.opacity};//                              `}}}// 鼠标移出,恢复到默认位置
banner.addEventListener("mouseout", function() {init()
})

5.静态页面弄好了以后,就可以给不同的图层赋值不同的移动速率了,鼠标移动的这个操作分为两个过程,第一,鼠标首次到达该区域,第二,鼠标移动。
鼠标刚到该区域的时候,是初始化的位置,无需任何操作,只需记录下鼠标的初始位置x_first即可,后面的操作根据这个初始位置进行translateX的动态赋值

// 鼠标悬浮,记录鼠标第一次到banner的位置x_first
banner.addEventListener("mouseover", function(e) {x_first = e.clientX// console.log(x_first);
})

鼠标移动过程中,x_new记录当前鼠标的位置,x_offset = x_first - x_new代表鼠标移动的位移,左移offset大于0,右移offset小于0,给每个图层的变化添加不同的层级level,这样就实现了不同图层具有不同的速率

let level = (15 - parseInt(k)) * 0.5;
let new_translateX = element_data.translateX + x_offset / level

还有一些细节就是,B站的第六张图片向右移动透明度逐渐增加,向左保持透明也就是opacity为0,第九、十章图片效果相反,所以添加了一些判断代码,注意:k是索引,从0开始,所以第六张图片的k是5,还有一个问题我没有解决的就是,这三张特殊的图片的opacity是逐渐变化的,而我没有找到最合适的效果,所以给他们设定了一个固定值0.333和0.44,目的达到了反正

if (k == 5 && x_offset < 0) {new_opacity = 0.333
} else if ((k == 8 || k == 9) && x_offset > 0) {new_opacity = 0.44
} else {new_opacity = element_data.opacity
}

然后就是修改img内联样式translateX的值

element.children[0].style = `transform: scale(1) translate(${new_translateX}px,${element_data.translateY}px ) rotate(0deg);filter: blur(${element_data.filter_blur}px);opacity:${new_opacity};`

这里,element不是img标签,而是img标签外面的div,所以通过.children[0]获取到img元素,进而改变其样式值

到这里,操作就完成了,然后,有什么意见,欢迎大家指正小白,毕竟啊,我是要成为代码王的男人,会虚心接受大家的指导的

仿B站首页头部动画的实现相关推荐

  1. 高仿支付宝首页头部动画

    高仿支付宝首页头部动画(使用design实现效果,CoordinatorLayout+AppBarLayout+CollapsingToolbarLayout+Toolbar) 效果图(效果图渐变不明 ...

  2. (https专业版)2018年1月5日高仿互站仿友价T5虚拟交易+实物交易商城-站长交易源码送手机版程序10套模版+首页微信登陆+头部下拉导航...

    (https专业版)2018年1月5日高仿互站仿友价T5虚拟交易+实物交易商城-站长交易源码送手机版程序10套模版+首页微信登陆+头部下拉导航 首页支持微信登陆,只有第8套模板支持(endv模板),后 ...

  3. 2022仿写b站首页

    仿写b站首页 ```html <!DOCTYPE html> <html lang="en"> <head><meta charset=& ...

  4. 2017年11月8日最新仿互站导航t5友价商城-9套模板首页都增加微信登陆

    今天测试效果如下,直接看图吧,入口在下方,点击图片直达 把9套餐模板都添加了微信首页登陆,仿互站的导航,操作比互站还要方便,官方一直对https 支持不太友好,索性把所有的https bug都修复了, ...

  5. 仿闲鱼 底部菜单html,GitHub - 494293346/rotateMenu: 仿闲鱼首页,“底部加号弹出菜单选项” 界面,动画效果可能跟闲鱼有点不一样...

    rotateMenu 仿闲鱼首页,"底部加号弹出菜单选项" 界面,动画效果可能跟闲鱼有点不一样 ##简介 仿闲鱼首页,"底部加号弹出菜单选项" 界面,动画效果可 ...

  6. html仿b站页面代码,B站首页界面设计:附详细教程

    文件名大小更新时间 B站首页界面设计:附详细教程\1.png2994402016-12-29 B站首页界面设计:附详细教程\2.png2492252016-12-29 B站首页界面设计:附详细教程\w ...

  7. UC浏览器首页滑动动画实现

    UC浏览器首页滑动动画实现 我们先来看下UC浏览器首页的滑动动画和我最终实现的动画效果 使用方式 <cn.ittiger.ucpage.view.UCIndexViewxmlns:android ...

  8. B站首页内容运营分析

    B站首页内容浅析 我们为什么要换首页? B站首页 整体分析 排行榜 内容推荐 内容标签化 用户标签化 探索B站优质内容之源 我们为什么要换首页? 换首页的目的是什么?改善用户体验?提高首页留存?提升C ...

  9. 推荐 9 个 GitHub 上练手项目(在线考试、仿美团、仿抖音、仿B站、仿头条...)

    GitHub项目推荐 推荐的这几个 GitHub 项目并不是简单的 XX 管理系统,我会从下面这些方向推荐几个入门级别但是不那么 Low 的项目. "我自己是一名从事了6年web前端开发的老 ...

最新文章

  1. 原创 | 大数据时代,应让“抗疫”更科学
  2. iOS--OCR图片识别
  3. HTML5从入门到精通(明日科技) 中文pdf扫描版
  4. python典型安装_python包的多种安装方式(内网)
  5. mysql 按照in id顺序_Mysql查询结果顺序按in()中ID的顺序排列的案例区分
  6. fit_transform和transform的区别
  7. Science | 从结构生物学的角度理解人类mRNA剪接体分支位点的识别
  8. 网络协议栈深入分析(四)--套接字内核初始化和创建过程
  9. 男性加入防晒大军 购买遮阳伞比例同比增长23.54%
  10. ai初创企业商业化落地_初创企业需要问的三个关于人工智能的问题
  11. 安卓实现tcp连接(安卓作为客户端,电脑作为服务端)
  12. 诺禾-蛋白表达纯化之通关技巧
  13. 笔记本禁用键盘和触摸板
  14. ecshop模板支持php,ecshop模板不支持引入PHP语句的解决方法
  15. 从WINDOW管理器差异,看WINDOWS与LINUX设计思想的文化内涵不同
  16. 关于Android 8.0/9.0 之后获取wifi名称为空的解决方法
  17. iOS home键直接退出
  18. 10.13(129. 求根到叶子节点数字之和 130. 被围绕的区域)
  19. precision and recall
  20. 配置Linux台式机作为服务器

热门文章

  1. 解决Win10系统过期失效问题的经验总结
  2. 二叉树+链表+字符串+栈和队列高频面试题合集,已开源下载
  3. 生活手机必备5款APP,一用就会上瘾,简直就是生活中的好帮手
  4. python下对bin文件的处理
  5. Linux CFS调度算法核心解析
  6. GAN中的Spectral Normalization
  7. Android 字体颜色渐变效果 Span实现
  8. 几行代码解决百度云视频变成 8秒净网公告问题(滑稽)
  9. 狄利克雷分布公式_潜在狄利克雷分配(LDA)
  10. WebSSH在线编程 所需工具介绍