大家好,我是 Steven。
今期我们会介绍怎样实现 BiliBili 秋季 的那个顶部图片横幅效果,当游标移过去的时候,随着左右移动,会有景深和对焦的效果。
这个教程的视频版在 www.bilibili.com/video/BV1NZ… ,欢迎三连关注!
HTML 的部分
打开 CodePen 编辑器,在 HTML 的部份加入一个 <header>
标签,然后里面加入六个 <div>
,每一个 <div>
里面加入一张图片。
这六张图片都是来自 BiliBili 的,图片版权归 BiliBili 所有,这里只用作教学用途。
我们先看看这六张图片,大小都一样的,是这个 Header Banner 不同的分层。将它们堆叠在一起,就可以组成一张完整的图片。
CSS 的部分
在 CSS 里,先加入 body
选择器,设定 margin
为 0
。
加入 header
选择器,高度设定为 160px
,position
设定为 relative
,overflow
设定为 hidden
。然后将里面的六个 <div>
重叠在一起,加入 header > div
选择器,position
是 absolute
,top
和 left
设定为 0
,宽度和高度设定为 100%
。
我想将里面的图片上下左右置中,加入 display: flex
,justify-content
和 align-items
设定为 center
,就可以了。
再加入 header > div > img
选择器,设定图片的样式。display
设定为 block
,宽度设定为 110%
,因为稍后图片会左右移动,为免穿帮,所以要将宽度加大一点,高度设定为 100%
,加入 object-fit: cover
,将图片按比例填满容器。
设定 CSS 变量
样式都设定好了,我们要再预留两个 CSS 变量,作为将图片左右移动,以及调整模糊度的功能。
加入 transform: translatex()
,设定值是 var(--offset)
,以及 filter: blur(var(--blur))
。那么我们接下来,就会通过 JavaScript,设定 --offset
和 --blur
的值,从而达到动画效果。
可以先设定 --offset
的预设值为 0px
,而 --blur
的预设值为 2px
。
JavaScript 的部分
来到 JavaScript 的部份,先定义一个常量 images
,获取所有图片回来。
然后在 header
那里,加入 addEventListener
监听 mousemove
游标移动事件。首先要计算移动的百份比,定义一个变量 percentage
,将 e.clientX
除以 window.outerWidth
,这样当游标移到最左时是 0
,移到最右时是 1
。然后定义变量 offset
,定义分层图片位置的距离,除了移动距离,还有模糊度,接下来就要将这些值套用到每一层的图片上。
先加入 for of
回圈,将所有图片获取出来,然后将 offset *= 1.3
,即是越后的图片,位移就会越多。再计算一下分层模糊度的值,这个算是我花最多时间思考怎样做的地方,原因是… 中学没有把数学学好。
这里要做到的是,游标在中间的时候,第 3 和第 4 张分层图片的模糊度最低,趋近于 0
,而第 2 和第 5 张图片模糊度较高,第 1 和第 6 张模糊度最高;而游标在右边的时候,第 6 张图片模糊度趋近于 0
,越往左的图片,模糊度越高。
这其实是一条很简单的数学公式,但就一直也想不起是什么公式,在想放弃前一秒终于想到,就是曲线的公式啦。
y = x^2 * 20
大概就是我们想达到的效果,所以,原来学好数学是很重要的呢。
回到这里,定义变量 blurValue
,将 index / images.length
减去 percentage
作为公式里的 x
,然后将它乘以 2
次方,再乘以 blur
,即是 20
。
最后,通过 setProperty()
,分别将位移和模糊度的值设定到 --offset
和 --blur
这两个 CSS 变量里。
我们来看看这个案例的完成效果
对了,BiliBili 的版本还有一个效果,就是她会眨眼,这个原理也很简单,他们准备了几张眨眼过程的图片,只需要使用 setInterval()
和 setTimeout()
定时将图片转换就可以了,在这就不特别介绍了。
以上,就是今集要介绍的全部内容。
这个案例的源代码在 codepen.io/stevenlei/p…
你的支持是我的动力,请关注 CodingStartup 起码课,我们一起加油!
- B站: space.bilibili.com/451368848
- YouTube: youtube.com/codingstart…
- 掘金: juejin.cn/user/249773…