开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第5天,点击查看活动详情
前言
今天写一个纯css鼠标移入移出效果,从div四个不同方向移入元素时,一块蒙板可以从对应方向滑入元素中,从div移出元素时,蒙板可以从对应方向滑出屏幕。
效果图如下:
解题思路
需要思考的最核心问题是如何判断鼠标从哪个方向移入?如果是用js的话我们很容易就可以通过监听mouseMove事件获取到移入位置,那么用css应该如何判断?
最容易的方法是把div元素分成上下左右四个区块,根据移入的所在区块,获得到鼠标的移入方向:
一开始我的想法是将元素的宽度和高度为0时,设置元素的边框宽度就会形成四个三角形,但是四个元素堆叠在一起会遮挡住其他的元素,所以后面使用clip-path裁剪元素,保证不会互相覆盖。
<div class="left block"></div>
<div class="right block"></div>
<div class="top block"></div>
<div class="bottom block"></div>
.block {
width: 100%;
height: 100%;
position: absolute;
left: 0;
top: 0;
z-index: 1;
clip-path: var(--clip-path);
}
.top {
--clip-path: polygon(0 0, 100% 0, 50% 50%);
background-color: red;
}
.bottom {
--clip-path: polygon(0 100%, 100% 100%, 50% 50%);
background-color: yellow;
}
.left {
--clip-path: polygon(0 0, 0 100%, 50% 50%);
background-color: green;
}
.right {
--clip-path: polygon(100% 0, 100% 100%, 50% 50%);
background-color: blue;
}
当鼠标移入四个block区域时,我们只需要给蒙板元素分别加一个对应方向的移入动画即可。
.mask {
width: 100%;
height: 100%;
position: absolute;
left: -100%;
top: 0;
background-color: rgba(17, 89, 156, 0.8);
--startX: 0;
--startY: 0;
--x: 0;
--y: 0;
animation: var(--animation-name) 0.3s linear;
animation-fill-mode: forwards;
color: white;
font-size: 44px;
display: flex;
justify-content: center;
align-items: center;
}
.top:not(.big):hover~.mask {
--startX: 100%;
--startY: -100%;
--x: 100%;
--y: 0;
--animation-name: runner;
}
.bottom:not(.big):hover~.mask {
--startX: 100%;
--startY: 100%;
--x: 100%;
--y: 0;
--animation-name: runner;
}
.left:not(.big):hover~.mask {
--startX: 0;
--startY: 0;
--x: 100%;
--y: 0;
--animation-name: runner;
}
.right:not(.big):hover~.mask {
--startX: 200%;
--startY: 0;
--x: 100%;
--y: 0;
--animation-name: runner;
}
@keyframes runner {
from {
transform: translateX(var(--startX)) translateY(var(--startY));
}
to {
transform: translateX(var(--x)) translateY(var(--y));
}
}
如果只是简单这样处理的话,还是会有问题,当鼠标快速的在元素内部移动时,会出现错乱,蒙板可能一会从上面下来,一会从左边出来,一会从右边出来,所以当移入某一个方向的块中之后,要挡住其他方向的块,让鼠标无法选中其他方向。
.block:not(.big):hover {
clip-path: unset;
z-index: 2;
}
当某一个方向块在hover状态下,取消裁剪属性,并且把该方向块的层级提高,挡住其他的元素块。
到这里,移入效果基本上已经完成了,接下来是解决另外一个问题:移出的时候方向该如何判断?
同理,我们可以做一个溢出层,用来判断超出元素块之后的方向。
鼠标移出效果
在元素外画一个更大的方向块,元素类名为big
当鼠标移入对应的溢出方向块时,设置对应移出动画。
源代码可查看:
优化展示效果
完成上面的移入和移出效果后,我发现还是有一些动画不够丝滑的地方:
- 溢出块太小,动画效果会卡顿;
- 快速移动鼠标到页面底部时,动画效果不明显;
优化方案:
- 当鼠标移动到某一个溢出块时,增加该溢出块大小,刚好覆盖住相邻元素的溢出块,此时还没进入到隔壁块,不会影响下一个块的动画,而且会延长移出动画时间。
- 当鼠标移入底部空时添加一个蒙板下移的动画效果,蒙板不会突然消失,使动画更丝滑。
- 适当缩短动画时间,这样比较容易欺骗眼睛,动画也会更加丝滑一些。
就是这么简单——Ending——