作者:盏灯
https://juejin.cn/post/7275576084128350248
看B站这个动画banner好几个版本了,不知道是一个月更新一次新版动画,还是多少天更新一次(没有天天去看,但估算是一月更新一版UI,以后注意观察)。刚看到的时候很感兴趣,不像视频素材或者gif素材,就放一个视频上去,或者放一个动态画上去,这个是根据鼠标动而一个小范围地有规律有弧度地动,很少看过。
只是看过一些比如视觉差的类似这样的根据鼠标动而动的动画,
举例说明:
1、先前的github404动画图片层第轴动特效页面(最近改版了,没有动画效果了,以前我写有一篇文章就是关于github星球大战为主题的404错误页面,对鼠标哦活动作出回应的相关代码,3d元素点睛);
github 404:
![图片[1]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_0.jpg)
2、视差引擎 parallax : [例子] (matthew.wagerfield.com/parallax/) 对光标的位置做出相应的反应。
parallax :
![图片[2]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_1.gif)
3、滚动动画(视差、动画、交互)ScrollMagic
多伦多24小时环保干洗店、修鞋、洗衣叠服服务网站Alfred
![图片[3]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_2.gif)
苹果vision产品页面
![图片[4]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_3.gif)
太多这种类似视觉差效果的产品图了,就不一一举例了,有兴趣的伙伴自行搜索...
前面讲到B站的首页的最上面一栏的根据鼠标的响应鼠标位置的视差效果。有的伙伴可能不怎么常去B站看(可能偶尔或者更多的是用手机端看),这边我贴一下效果,如下:
![图片[5]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_4.gif)
确实是想看一下是怎么做的。然后我就去搜,结果你可以去看看,印象很深的是一个人讲过(这里我就不讲了,可以搜搜看),反正就是提出了问题,问了观众是怎么做的,然后最后的结论是就是根据鼠标移动而移动。
"Talk is cheap, show me the code. —— Linus Torvalds" (直接翻译就是说话容易,给我展示代码),这个人的一句名言,也代表了他对实际代码和行动的重视,而不是停留口头的吹吹说说假大空。真正的生产力和进步是基于编写(或者集成他人的)代码的质量和效率,而不是单单谈论功能、空想事情的所有方式等等)。
有时候设计的时候概念很简单脱口而出,但是实际实现中需要做的工作是要多得多的(相信很多开发者在开发时候对这句话深有体会,说说说、说出花来、吹得天花乱坠,但是做,又是做不出个所以然来。所以说到一定程度,但好像没什么进展的时候,就得“多说无用,给我看你的行动”了,我笃信,无论是工作上还是人际关系上都是如此)。
所以,类似经常说的写作就是思考,那么我相信编程就是思考这句话也是同样富含逻辑和道理的。
接下来我们看一下是如何实现的
准备工作——素材
一共15张素材,15张素材构成一幅图。叫UI设计组小姐姐做。如若PS技术强,可以自己搞(先画出整体图,构想整体需要什么场景的、人和物和景,对了,然后一层一层关闭图层保存矢量图给前端),根据鼠标有规律(这里规律是指有范围、有移动偏移曲线、有透明度变化、有缩放变化等等地动)这个不知道是不是有产品经理给效果图给到UI小姐姐、给到前端去看最终效果,从而做出来的。
编程第一步:建一个html文件
不想着后面有多难,但至少这一步建文件我是会的,我正规点,建个文件夹,文件夹里建一个banner.html文件,再建一个static文件夹用来放素材。第一步就基本也错不到哪里去,大不了错了我再删,删了我再建。
该文用原生先写一遍,下一篇我再用vue或者react搞一遍,不喜欢看或者目前用不上原生的js来搞这个动画效果的可以到这里结束了,可以去B站首页自行体验体验。
建完文件的第一步:! + Tab
vscode !+Tab,完事,又进了一步。
![图片[6]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_5.jpg)
画底色
子内容重复循环的。那么,外框先画好。子内容接下来再想。
![图片[7]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_6.jpg)
![图片[8]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_7.jpg)
编写代码观察,定义好数据结构
观察别人是怎么做的。其实这一步,应该从一开始就应该一直贯彻到末尾。只不过,做完上一步不知道下一步怎么做了,为了尽量可能接近结果,就先观察,把会做的,先做了。这里值得一提的是:控制台(控制台是一个很好的高分优秀答题者,有时候从控制台找答案会比我自己空想来得要完整和有用)。
![图片[9]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_8.jpg)
<div class="layer"><imgsrc="素材"style="高度; 宽度; transform: translate(x, y) rotate(角度) scale(缩小或放大); opacity: 透明度;"></div>// .// .// .// 以此类推,15个素材元素,正好15个这样差不多的dom结构,(也可推测这是个数组,用来循环,开发如果所有东西都类似的东西手动一个个写人会疯掉且,即使愿意不怕累那也使不得,因为量大效率不高。所以这里用循环来搞)// 而且如果下次要换不同的元素或者版块,改数据就好,不需要改其他。// 那么数据结构是什么样子的呢?...
layers 数组数据结构:
const layers = [ { resources: [ { src: './static/4e7edb416c34eccc40f34d2b297524652685a9bb.png', id: 0 } ],scale: {initial: 0.6,},rotate: {},translate: {},blur: {},opacity: {wrap: "clamp",},name: '01 bg'},以此类推(有多少素材就有多少个对象,定义好素材地址、scale缩放、rotate旋转、translate偏移量、blur模糊度、opacity透明度、文件名备注): {}]
一切以中心原点为定值:
01 bg
![图片[10]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_9.jpg)
![图片[11]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_10.jpg)
13 远鸟
![图片[12]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_11.jpg)
![图片[13]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_12.jpg)
02 灯塔丛林
![图片[14]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_13.jpg)
![图片[15]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_14.jpg)
03 底部海水
![图片[16]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_15.jpg)
![图片[17]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_16.jpg)
04 鳄鱼a
![图片[18]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_17.jpg)
![图片[19]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_18.jpg)
04 鳄鱼b
![图片[20]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_19.jpg)
![图片[21]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_20.jpg)
05 左边鱼影
![图片[22]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_22.jpg)
06 左边鱼群
![图片[23]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_23.jpg)
![图片[24]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_24.jpg)
07 右边鱼
![图片[25]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_26.jpg)
08 右边鸟
![图片[26]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_27.jpg)
![图片[27]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_28.jpg)
09 中间
![图片[28]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_29.jpg)
![图片[29]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_30.jpg)
11 33
![图片[30]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_31.jpg)
![图片[31]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_32.jpg)
10 水面
![图片[32]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_33.jpg)
![图片[33]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_34.jpg)
12 近鸟
![图片[34]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_35.jpg)
![图片[35]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_36.jpg)
14 两侧
![图片[36]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_37.jpg)
![图片[37]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_38.jpg)
给每个素材定宽高
这一步就是根据上面的数据结果,给每个素材设置一下宽高。其中要看scale的值和相对它们来说最大的外框.animated-banner的高度来响应式地对每个素材的宽高进行处理。
![图片[38]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_39.jpg)
(注:如若看不清,右击在新标签页打开图片查看)
给每个元素加个div
这一步就直接给每个img加个div。class为layer。
css 需要加上这个layer的样式:
.layer {position: absolute;left: 0;top: 0;height: 100%;width: 100%;display: flex;align-items: center;justify-content: center;}
js 需要加上:
const divElementArr = layers.map(() => {const divElement = document.createElement('div')divElement.classList.add('layer')banner.appendChild(divElement)return divElement})
最后得到的是一个数组,每一个(这里有15个)元素class为layer的div。然后append到.animated-banner最大boss上。
![图片[39]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_40.jpg)
append素材到layer的div上
append素材元素,追加上去,代码如下:
layers.map((layer, layerKey) => {const layerElement = layer.resources[0].eldivElementArr[layerKey].appendChild(layerElement)})
这个时候就得到效果图如下:
![图片[40]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_41.jpg)
可以看到,所有的元素都以正中心排布(原因就是上面的css中相对定位所有都center水平居中垂直居中)。
那这个时候就说了,下一步是不是根据数据结构,给每个元素距离正中心偏移多少设置了。没错的。
初始样式设置 以及 每个元素距离正中心偏移排布
初始样式设置
![图片[41]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_42.jpg)
// 鼠标指针相对窗口边缘水平坐标 左还是右,左进则是正数比率,右进则是负数比率let relativeX = 0;
每个元素距离正中心偏移排布
![图片[42]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_43.jpg)
一开始加载元素的偏移排布
![图片[43]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_44.jpg)
鼠标监听事件
![图片[44]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_45.jpg)
效果图
![图片[45]-前端开发,实现B站首页动态banner-JieYingAI捷鹰AI](https://www.jieyingai.com/wp-content/uploads/2024/09/1726336930507_46.gif)
总结
此次文章研究B站的动图如何实现(实现transform中的translate如何如何一比一还原,篇幅太大缩放大小、透明度,以及moveleave还没仔细讲解),但基本上同一原理,这里难点重点是贝塞尔曲线,元素按曲线运动以及左右移动换鳄鱼图,以及透明度的问题。
完成上面的点







