【网页特效】丝滑的 macOS Dock效果
点击上方 前端Q,关注公众号
回复加群,加入前端Q技术交流群
今期我们又来做一些花里胡哨的特效,就是模仿 macOS 的 Dock 这个图标放大的效果:
如果是单纯的逐个图标放大,其实就没什么难度。不过我们的作风是,要做就做得够细致,当游标在同一个图标上左右移动时,都会影响到左边和右边的图标大小的,达到一个很连贯的效果,这个就是今次的难度所在。
好了,那我们就开始吧。
HTML 的部分
打开 CodePen 编辑器,在 HTML 的部分加入一些图标,在这里我会用 Emoji 表情符号来代表,加入一个 <ul>
列表的标签,class
设定为 dock
,然后用 <li>
装着每一个表情符号,再在外面套上一层 <div>
,class 是 glass
。
CSS 的部分
然后是 CSS 的部分,加入 html
选择器,把基础的文字大小设定为 15px
。加入 body
选择器,将 margin
和 padding
设定为 0
,display
设定为 flex
,宽度设定为 100%
,min-height
最小的高度设定为 100vh
,overflow
设定为 hidden
。
然后要把它定位到页面的下方,align-items
设定为 flex-end
。
加入 .glass
选择器,宽度设定为 100%
,高度设定为 8rem
,然后背景颜色设定为浅灰色,display
设定为 flex
,justify-content
设定为 center
。
加入 .dock
选择器,将图标居中以及横向排列,list-style
列表的样式设定为 none
,margin
和 padding
设定为 0
,display
设定为 flex
,justify-content
和 align-items
设定为 center
。
再设定图标的样式,加入 .dock li
选择器,由于这里用的是表情符号,所以可以通过设定 font-size
来调整它的大小,font-size
设定为 6rem
。然后加入一些 padding
,左右设定为 0.5rem
,cursor
游标的样式设定为 default
即是预设的箭头。
好了,样式的部分都差不多了,接下来就是实现特效的部分。
动画的原理
首先我们了解一下这个效果的原理,举例我们将游标移动到第四个图标上的时候,它会放大。除此之外,在它旁边的第三个和第五个图标都会稍为放大一点,而当游标的位置比较靠左的时候,第三个就会比第五个放大一点,反之亦然。
所以我们就要知道游标在某一个图标上的时候,是在左边,中间还是右边的位置。
JavaScript 的部分
来到 JavaScript 的部分,先用 querySelectorAll()
把所有 .dock li
获取回来。然后通过回圈,为每一个 li
加入 mousemove
事件监听器。
定义一个变量 item
,赋值为 e.target
,因为稍后会多次引用到。然后要知道图标所在的 li
容器的宽度,定义变量 itemRect
,赋值为 item.getBoundingClientRect()
。
然后就是计算游标在图标上的位置,定义变量 offset
,赋值为 e.clientX
减去 itemRect.left
,由于它可能是负值,所以套上 Math.abs()
,再除以 itemRect.width
。
现在当游标移到图标左边的时候,offset
会趋近于 0
,移到右边的时候,offset
会趋近于 1
。
有了这个值,我们就可以计算图标的放大比例了。定义两个变量,分别是 prev
和 next
,通过 previousElementSibling
以及 nextElementSibling
获取当前游标所在的图标,前一个以及后一个的 li
元素。
再定义一个变量 scale
,假如我想图标放到最大是 1.6
倍,这里就赋值为 0.6
。
然后就计算放大的比率,并且写入到对应元素的 CSS 变量之中。在设定 prev
之前,要先判断一下是否能够获取到到它,因为当游标在第一个图标上的时候,prev
就会是 null
。然后通过 setProperty()
,将放大的比率设定到 CSS 的变量里面,我会设定为 1
加上 scale
乘以 Math.abs(offset \- 1)
,offset \- 1
是因为现在正在设定左边的元素,所以 offset
的值要相反,即是将 0
至 1
改为 1
至 0
。
然后运用相同的逻辑设定右边元素的放大比率,不同的是,这里的 offset
直接使用就可以了,而对于当前的图标呢,就直接设定为 1 + scale
就是最大值了。
定义一个用于重置 --scale
的函式,名为 resetScale()
,把所有 li
的 --scale
重置为 1
。
总共有两处位置需要执行这个函式的,分别是在 mousemove
事件里面,以及当游标离开这个 Dock 的时候。新增 mouseleave
事件监听器,并且执行 resetScale()
,就可以了。
通过开发者工具,看一下 --scale
的变化:
在游标移动的过程当中,会将超出范围的 li
的 --scale
重置为 1
,以及在游标离开 Dock 的时候,所有 li
的 --scale
都重置为 1
。
最后一步
好了,来到这里,就差一步就完成了。
回到 CSS 的部份,将文字大小的设定值更改为 6rem
乘以 var(--scale)
,因为涉及到运算,所以套上一层 calc()
。
在 .dock
选择器内初始化 --scale
为 1
。测试一下:
放大效果就达到了,不过定位有点问题。这个也不难解决,将 position
设定为 relative
。然后计算一下 top
相对于图标放大后的位移就可以了。再增加一点点的 transition
动画过渡的设定。
我们顺便将点击图标然后载入中的效果都做出来吧,如果你有兴趣的话,暂停一下,试试自己实现一下。
这里也很简单,定义一个叫做 loading
的动画设定,通过 translateY()
将它上下移动,然后加入 .dock li.loading
选择器,即是当 li
有 loading
这个 class 的时候,执行这个动画,并且无限次重覆。
再到 JavaScript 的部分,加入针对 li
的点击事件监听器,然后为目标的元素加上 loading
这个 class
就可以了。
我们来看看这个案例的完成效果
以上,就是今期要介绍的全部内容。
案例源代码请在公号回复关键字 macOS Dock 效果获取
转自:CodingStartup起码课
https://juejin.cn/post/6942325271349592100
内推社群
我组建了一个氛围特别好的腾讯内推社群,如果你对加入腾讯感兴趣的话(后续有计划也可以),我们可以一起进行面试相关的答疑、聊聊面试的故事、并且在你准备好的时候随时帮你内推。下方加 winty 好友回复「面试」即可。