前端开发,实现B站首页动态banner

原文来源于:程序员成长指北

如有侵权,联系删除

看B站这个动画banner好几个版本了,不知道是一个月更新一次新版动画,还是多少天更新一次(没有天天去看,但估算是一月更新一版UI,以后注意观察)。刚看到的时候很感兴趣,不像视频素材或者gif素材,就放一个视频上去,或者放一个动态画上去,这个是根据鼠标动而一个小范围地有规律有弧度地动,很少看过。

只是看过一些比如视觉差的类似这样的根据鼠标动而动的动画,

举例说明:

1、先前的github404动画图片层第轴动特效页面(最近改版了,没有动画效果了,以前我写有一篇文章就是关于github星球大战为主题的404错误页面,对鼠标哦🖱活动作出回应的相关代码,3d元素点睛);

github 404:

图片

2、视差引擎 parallax : [例子] (matthew.wagerfield.com/parallax/) 对光标的位置做出相应的反应。

parallax :

图片

3、滚动动画(视差、动画、交互) ScrollMagic

多伦多24小时环保干洗店、修鞋、洗衣叠服服务网站Alfred

图片

苹果vision产品页面

图片

太多这种类似视觉差效果的产品图了,就不一一举例了,有兴趣的伙伴自行搜索🔍...

前面讲到B站的首页的最上面一栏的根据鼠标的响应鼠标位置的视差效果。有的伙伴可能不怎么常去B站看(可能偶尔或者更多的是用手机端看),这边我贴一下效果,如下:

图片

确实是想看一下是怎么做的。然后我就去搜,结果你可以去看看,印象很深的是一个人讲过(这里我就不讲了,可以搜搜看),反正就是提出了问题,问了观众是怎么做的,然后最后的结论是就是根据鼠标移动而移动。

"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,完事,又进了一步。

图片

画底色

子内容重复循环的。那么,外框先画好。子内容接下来再想。

图片

图片

编写代码

观察,定义好数据结构

观察别人是怎么做的。其实这一步,应该从一开始就应该一直贯彻到末尾。只不过,做完上一步不知道下一步怎么做了,为了尽量可能接近结果,就先观察,把会做的,先做了。这里值得一提的是:控制台(控制台是一个很好的高分优秀答题者,有时候从控制台找答案会比我自己空想来得要完整和有用)。

图片

<div class="layer">
    <img 
        src="素材" 
        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

图片

图片

13 远鸟

图片

图片

02 灯塔丛林

图片

图片

03 底部海水

图片

图片

04 鳄鱼a

图片

图片

04 鳄鱼b

图片

图片

05 左边鱼影

图片

图片

06 左边鱼群

图片

图片

07 右边鱼

图片

图片

08 右边鸟

图片

图片

09 中间

图片

图片

11 33

图片

图片

10 水面

图片

图片

12 近鸟

图片

图片

14 两侧

图片

图片


给每个素材定宽高

这一步就是根据上面的数据结果,给每个素材设置一下宽高。其中要看scale的值和相对它们来说最大的外框.animated-banner的高度来响应式地对每个素材的宽高进行处理。

图片

(注:如若看不清,右击在新标签页打开图片查看)

给每个元素加个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上。

图片

append素材到layer的div上

append素材元素,追加上去,代码如下:​​​​​​​

layers.map((layer, layerKey) => {    const layerElement = layer.resources[0].el    divElementArr[layerKey].appendChild(layerElement)})

这个时候就得到效果图如下:

图片

可以看到,所有的元素都以正中心排布(原因就是上面的css中相对定位所有都center水平居中垂直居中)。

那这个时候就说了,下一步是不是根据数据结构,给每个元素距离正中心偏移多少设置了。没错的。

初始样式设置 以及 每个元素距离正中心偏移排布

初始样式设置

图片

// 鼠标指针相对窗口边缘水平坐标 左还是右,左进则是正数比率,右进则是负数比率let relativeX = 0;

每个元素距离正中心偏移排布

图片

一开始加载元素的偏移排布

图片

鼠标监听事件

图片

效果图

图片

总结

此次文章研究B站的动图如何实现(实现transform中的translate如何如何一比一还原,篇幅太大缩放大小、透明度,以及moveleave还没仔细讲解),但基本上同一原理,这里难点重点是贝塞尔曲线,元素按曲线运动以及左右移动换鳄鱼图,以及透明度的问题。

  • 7
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值