【动画进阶】神奇的卡片 Hover 效果与 Blur 的特性探究
本文,我们将一起探讨探讨,如下所示的一个卡片 Hover 动画,应该如何实现:
这个效果的几个难点:
- 鼠标移动的过程中,展示当前卡片边缘的 border 以及发光效果;
效果只出现在鼠标附近?这一块的实现方法就有很多种了,可以计算鼠标附近的范围,在范围内去实现的效果,但是这样成本太高了。
转换一下思维,其实也可以利用遮罩的思想。在一开始就已经实现好了整体效果,也就是渐变色的整个边框以及整体的内发光效果,通过遮罩的思想,让整个遮罩层跟随鼠标进行移动。
- 整体的效果需要适配鼠标的移动,跟随鼠标移动,进行效果的切换;
基于上述动图中,到目前为止,纯 CSS 在鼠标移动效果跟随上,是没法解决的,这里需要引入一定量的 Javascript 代码。
基于上述难点(1)(2),下面我们就一起看看如何一步一步实现这个效果。
搭建整个静态效果
首先,我们需要搭建整个静态效果。也就是在没任何 hover 的状态下的效果,如下所示:
由于,每张图背后的虚化图效果,应该是基于图片不同而千图千面,因此,不可能能够用一张背景图 Cover 所有情况。
并且,图片背后的虚化图的效果,需要与实际图片的颜色保持大致一致。
基于上述两点,我们很容易想到使用 filter: blur()
模糊来处理此类情况。
代码也比较简单:
<div></div>
:root {
--pic: url("https://oss.aiyuzhou8.com/2023/05/08-.jpg");
}
div {
position: relative;
margin: auto;
width: 350px;
height: 500px;
border-radius: 30px;
overflow: hidden;
&::before,
&::after {
content: "";
position: absolute;
background: var(--pic);
background-size: cover;
background-position: center;
border-radius: 30px;
}
&::before {
inset: 0;
filter: blur(20px);
}
&::after {
inset: 50px;
}
}
这里,我们用元素的一层伪元素实现原图,另外一层伪元素实现虚化后的图片:
这种好处是,背后的虚化图层,可以适配任意的不同图片:
实现渐变色边框
接下来,我们需要实现渐变色的边框效果。
这个需要借助 conic-gradient
实现。
我们需要借助另外一个 div 实现我们的效果:
<div></div>
div {
width: 350px;
height: 500px;
border-radius: 30px;
background: conic-gradient(#03a9f4, #e91e63, #9c27b0, #ff5722, #03a9f4);
}
这样,我们就得到了一个这样的图形:
把它叠加到我们上述的效果之上,让整个图形,稍微比上述虚化背景大一点点即可,如此一来,效果就变成了这样:
仔细看,图片带上了渐变色的边框。
等等,再仔细看!除了渐变色边框之外,当前的效果,居然还自带了内发光(内阴影)效果,真是歪打正着,这不正是我们需要实现的吗:
探究 filter: blur()
的透明效果
这是为何呢?原因在于,设置了 filter: blur()
的元素,会从边缘处向中心处,带有透明衰减的效果。
我们简单来做个实验:
<div></div>
<div></div>
div {
position: relative;
width: 200px;
height: 300px;
border-radius: 10px;
border: 1px solid #000;
background: conic-gradient(#03a9f4, #e91e63, #9c27b0, #ff5722, #03a9f4);
&::before {
content: "";
position: absolute;
inset: 10px;
border-radius: 10px;
background: #fff;
border: 1px solid #000;
}
}
我们设置了两个一模一样的 div,其中,元素本身设置了一个角向渐变背景。
接着,利用其伪元素,在元素中间相距边界 10px
的地方,设置一个背景为白色的元素。效果如下:
此时此刻,两个元素没有任何不一样。但是接下来,我们给第二个元素的伪元素,添加上一个 filter: blur()
高斯模糊效果:
div:nth-child(2) {
&::before {
filter: blur(20px);
}
}
此时,再看看效果:
在白色元素的边缘处,向内的方向,其实是有逐渐减弱的透明效果。
当然,由于高斯模糊还会产生向外扩散的效果,因此上述 DEMO 示意图看起来不是很清晰,我们可以通过多套一层容器,通过 overflow: hidden
阻止高斯模糊的向外扩散。
我们再调整一下布局:
<div class="g-father">
<div class="g-child"></div>
</div>
<div class="g-father">
<div class="g-child"></div>
</div>
.g-father {
position: relative;
width: 200px;
height: 300px;
border-radius: 10px;
border: 1px solid #000;
background: conic-gradient(#03a9f4, #e91e63, #9c27b0, #ff5722, #03a9f4);
.g-child {
position: absolute;
inset: 10px;
border-radius: 10px;
border: 1px solid #000;
overflow: hidden;
&::before {
content: "";
position: absolute;
inset: 0;
background: #fff;
border-radius: 10px;
}
}
}
.g-father:nth-child(2) {
.g-child::before {
filter: blur(20px);
}
}
此时,我们再看整个效果,设置了 filter: blur()
的元素,会从边缘处向中心处,带有透明衰减的效果就非常明显了:
完整的 DEMO,你可以戳这里:CodePen Demo -- filter: blur 透明效果示意
鼠标移动事件监听配合 mask,实现整体效果
好,到这里,我们已经成功得到了这么一个效果:
基于上述效果,我们最后要做的,就是最终实现这么个效果:
这里,我们会利用鼠标移动事件监听配合 mask 来实现。
由于我们上述的效果是分层实现的,其中边框和内发光层,其实是这么个背景效果:
我们要做的就是:
- 利用
radial-gradient()
实现一个径向渐变 mask 遮罩; - 监听鼠标移动事件,移动 mask 遮罩的中心点;
- 可以通过多设置一层,实现 Hover 时背景角向渐变元素才出现,鼠标离开元素区域,背景角向渐变元素消失;
大致代码如下:
<div id="g-container">
<div id="g-img"></div>
</div>
:root {
--x: 0;
--y: 0;
}
#g-container {
position: relative;
width: 350px;
height: 500px;
border-radius: 30px;
}
#g-img {
position: absolute;
inset: 0px;
border-radius: 30px;
background: conic-gradient(#03a9f4, #e91e63, #9c27b0, #ff5722, #03a9f4);
mask: radial-gradient(
circle at var(--x) var(--y),
#000,
#000,
transparent,
transparent,
transparent
);
}
const container = document.getElementById("g-container");
const img = document.getElementById("g-img");
container.addEventListener("mousemove", (event) => {
img.style.visibility = 'visible';
const target = event.target;
const rect = target.getBoundingClientRect();
var offsetX = event.clientX - rect.left;
var offsetY = event.clientY - rect.top;
var percentX = (Math.min(Math.max(offsetX / rect.width, 0), 1) * 100).toFixed(2);
var percentY = (Math.min(Math.max(offsetY / rect.height, 0), 1) * 100).toFixed(2);;
console.log('X: ' + percentX + '%');
console.log('Y: ' + percentY + '%');
container.setAttribute('style', `--x: ${percentX}%;--y: ${percentY}%;`);
});
container.addEventListener("mouseout", (event) => {
img.style.visibility = 'hidden';
});
在图形上方移动鼠标,我们可以得到这么一个效果:
好,将上述的前面两个图层也合并进来,这样,我们就最终完美的实现了我们想要的效果:
完整的代码散落在上方,就不重复贴影响阅读体验了,感兴趣的同学,可以戳这里获取完整 DEMO 效果及源码:
CodePen Demo -- CSS 3D Rotate With Mouse Move DEMO
最后
好了,本文到此结束,希望本文对你有所帮助
想 Get 到最有意思的 CSS 资讯,千万不要错过我的公众号 -- iCSS前端趣闻
更多精彩 CSS 技术文章汇总在我的 Github -- iCSS ,持续更新,欢迎点个 star 订阅收藏。
如果还有什么疑问或者建议,可以多多交流,原创文章,文笔有限,才疏学浅,文中若有不正之处,万望告知。
【动画进阶】神奇的卡片 Hover 效果与 Blur 的特性探究的更多相关文章
- css 卡片hover效果
.card { height: 430px; width: 100%; background:#ffffff; border:1px solid #eaeefb; border-radius:5px; ...
- 一个纯CSS实现的卡片翻转效果
先上代码 <div id="box"> <div class="front">正面</div> <div class= ...
- 【特效】体验很好的导航hover效果移出恢复当前位置
很常见的一种导航的hover效果,鼠标放上后除了正常的hover,在移出整个导航后,会恢复当前栏目的特殊样式,分别有横向和纵向的导航.代码也比较简单,设置一个当前栏目的class,用index()找到 ...
- 好看的鼠标hover效果
0919自我总结 常见的鼠标hover效果 展示效果:http://ianlunn.github.io/Hover/ 部分动画制作 <style><!-- .container { ...
- Three.js 进阶之旅:物理效果-3D乒乓球小游戏 🏓
声明:本文涉及图文和模型素材仅用于个人学习.研究和欣赏,请勿二次修改.非法传播.转载.出版.商用.及进行其他获利行为. 摘要 本文在专栏上一篇内容<Three.js 进阶之旅:物理效果-碰撞和声 ...
- jQuery手机端触摸卡片切换效果
效果:http://hovertree.com/code/run/jquery/a1gr3gm9.html 可以用手机查看效果. 代码如下: <!doctype html> <htm ...
- Web页面中5种超酷的Hover效果
hover 效果能给网页增加一些动态效果,并且使得站点更具有活力.原来的做法是使用javascript来实现这些动态效果,但是随着CSS3的引入和现代浏览器 的支持,我们可以用纯粹的CSS代码来实现这 ...
- 使用 SVG 动画实现弹性的页面元素效果
Codrops 分享了一些给SVG元素加上弹性动画的灵感.实现的思路是把一个SVG元素整合成一个组件,然后从一个路径弹性动画到另一个.这种效果可以应用到像菜单,按钮或其它元素,使得交互更有趣,看起更原 ...
- SVG 动画实现弹性的页面元素效果
Codrops 分享了一些给SVG元素加上弹性动画的灵感.实现的思路是把一个SVG元素整合成一个组件,然后从一个路径弹性动画到另一个.这种效果可以应用到像菜单,按钮或其它元素,使得交互更有趣,看起更原 ...
- Swift 版本很好的卡片切换效果基于ZLSwipeableView
前言:在这篇文章你可以学到,一些基本的Swift语法, 基本UI控件闭包等. 实际的效果,比gif图的效果好很多. 卡片切换.gif 首先需要导入ZLSwipeableView pod 'ZLSwip ...
随机推荐
- 推荐一个vs Nuget部署插件
写在前面 nuget部署工具, 无论是直接用web上传还是用命令行工具上传,还是其他第三方工具我都没找到满意,直到那天在群里提了一下,有位大佬说了个NuPackvs插件,用了下,感觉基本满足了我的需求 ...
- 面试官:transient关键字修饰的变量当真不可序列化?我:烦请先生教我!
一.写在开头 在这篇文章中记录一下之前自己面试时学到的东西,是关于transient关键字的,当时面试官问我IO的相关问题,基本上全答出来了,关于如何不序列化对象中某个字段时,我果断的选择了stati ...
- 配置 Gerrit 迁移
https://gerrit.googlesource.com/plugins/replication/+doc/master/src/main/resources/Documentation/con ...
- 如何在不能求逆的时候做子集卷积 exp(即便能求逆也比常见方法优雅)
为什么要求逆?正常做子集卷积 exp 的时候递推求 \(G=\exp(F)\) 的系数时要用. 什么情况下不能求逆?模 \(2^{64}\),或者压根不取模. 我们可能会想,算出来肯定除得尽啊,因为组 ...
- Win10 内存内存占用过高的一种解决方案
前言 最近win10的电脑一开机,什么都没启动,内存占用率高达90%,笔记本虽然是8G的内存,但不应该如此不堪.在网上找到一个十分有效的解决方案. 正文 使用 win10系统自带内存诊断工具 按下 h ...
- 实现ASP.Net Core3.1运行在DockeDesktop下并用Nginx实现负载均衡
一.首先去https://docs.docker.com/get-docker/下载Windows版本的Docker Desktop并安装(需要win10专业版以上操作系统,并启用CPU虚拟化和安装H ...
- yb课堂 基于浏览器和node.js的http客户端Axios 《三十四》
什么是Axios 基于promise用于浏览器和node.js的http客户端 支持浏览器和node.js 支持Promise API 支持拦截请求和响应 支持转换请求和响应数据 JSON数据的自动转 ...
- Pypi配置API Token
技术背景 在许久之前写的一篇博客中,我们介绍过使用twine向pypi上传我们自己的开源包的方法.最近发现这个方法已经不再支持了(报错信息如下所示),现在最新版需要使用API Token进行文件上传, ...
- WPF/C#:在WPF中如何实现依赖注入
前言 本文通过 WPF Gallery 这个项目学习依赖注入的相关概念与如何在WPF中进行依赖注入. 什么是依赖注入 依赖注入(Dependency Injection,简称DI)是一种设计模式,用于 ...
- 使用Eclipse开发Vue——CodeMix够智能
使用Eclipse开发Vue--CodeMix够智能 Eclipse的CodeMix插件允许您访问 VS Code和Code OSS扩展社区,以及 Webclipse 1.x 功能. Vue.js是构 ...