纯 CSS 如何实现按钮的水滴动画效果? 下面本篇文章就来给大家介绍一下使用纯 CSS 实现 Material Design 中按钮的水滴动画效果. 有一定的参考价值, 有需要的朋友可以参考一下, 希望对大家有所帮助.
前言
大家平时应该经常见到这种特效, 很炫酷不是吗
这是谷歌 Material Design 中最常见的特效了, 市面上也有很多现成的 JS 库, 用来模拟这一特效. 但是往往要引入一大堆 JS 和 CSS, 其实在已有的项目中, 可能只是想加一个这样的按钮, 来增强用户体验, 这些 JS 库就显得有些过于庞大了, 同时由于是 JS 实现, 很多时候还要注意加载问题.
那么, 有没有办法用 CSS 来实现这一特效呢?
思路
其实就是一个动画, 一个正圆从小变大, 用 css3 中的动画很容易实现
示例代码
- @keyframes ripple{
- from {
- transform: scale(0);
- opacity: 1;
- }
- to {
- transform: scale(1);
- opacity: 0;
- }
- }
通常用 JS 来实现的方式很简单, 就是给点击元素添加一个 class, 然后再动画结束后移除该 class
示例代码
- var btn = document.getElementById('btn');
- btn.addeventlistener('click',function(){
- addClass(btn,'animate')
- },false)
- btn.addeventlistener('transitionend',function(){// 监听 css3 动画结束
- removeClass(btn,'animate')
- },false)
那么如何通过 CSS 来实现动画的触发呢?
CSS 实现
CSS 中与鼠标交互的伪类主要有
hover 鼠标经过
:active 鼠标按下
:focus 鼠标聚焦
:checked 鼠标选中
很多情况下, 我们页面中的效果都是通过 hover 来实现的, 鼠标放上去触发一个效果, 离开还原, 但是如果放上去马上离开, 那么动画也会马上结束.
我们先试一下.
结构
这是我们写好的页面结构和样式
- <style>
- .btn{
- display: block;
- width: 300px;
- outline: 0;
- overflow: hidden;
- position: relative;
- transition: .3s;
- cursor: pointer;
- user-select: none;
- height: 100px;
- text-align: center;
- line-height: 100px;
- font-size: 50px;
- background: tomato;
- color: #fff;
- border-radius: 10px;
- }
- </style>
- <a class="btn">button</a>
很简单, 就是一个普通的按钮样式
下面我们在按钮中添加我们需要的正圆.
我们用伪元素来实现
- .btn:after{
- content: '';
- position: absolute;
- width: 100%;
- padding-top: 100%;
- background: transparent;
- border-radius: 50%;
- left: 50%;
- top: 50%;
- transform: translate(-50%,-50%)
- }
我们把上面的 overflow: hidden 去掉, 把这个圆缩小一点看看效果
然后, 我们写个缩放的动画
- @keyframes ripple{
- from {
- transform:translate(-50%,-50%) scale(0);
- /** 由于我们默认写了变换属性, 所以这里要补上 translate(-50%,-50%), 不然就会被替换了 **/
- background: rgba(0,0,0,.25);
- }
- to {
- transform:translate(-50%,-50%) scale(1);
- background: transparent;
- }
- }
hover 小交互体验
鼠标经过试试?
- .btn:hover:after{
- animation: ripple 1s;
- }
效果还是不错的, 就是如果鼠标离开的太快, 那么刚刚扩大的圆马上就缩回去了, 有点违和
但是这不是我们想要的效果呀. 我们希望的是点击一次触发一次, 而不是这样放上去就完了, 再也不会触发了.
active 尝试
平时工作中, active 用到的也比较多, 通常是用在点击的效果上, 那么拿来试试?
- .btn:active:after{
- animation: ripple 1s;
- }
效果也是差强人意, 有点类似鼠标按住的意思, 你必须一直按住鼠标, 才能完整的触发, 比如说上面的例子, 动画的运行实现是 1s, 那么你必须点在那个按钮上持续 1s 才能看到完整的动画效果, 否则, 就像上面鼠标离开一样, 动画马上就缩回去了
focus 体验
如果需要让任意一个元素获焦, 你可以给太指定一个 tabindex 属性
- <a class="btn" tabindex="1">button</a>
- .btn:focus:after{
- animation: ripple 1s;
- }
foucs 也可以触发, 只是触发以后只有等失去焦点之后才能再次触发, 实际的操作表现就是, 点过一次以后, 再点一下外面的空白
难道就没有办法了吗?
当然还是有的, 放在最后的肯定就是解决方式, haha
checked
checked 并不能直接触发, 这是表单元素选中后触发的, 为此, 我们需要改造一下页面结构
- <label class="btn">
- <input type="checkbox"><span>button</span>
- </label>
我们这里换成了 lable 并计入了 input[type=checkbox] 标签, 主要是为了在点击按钮的时候触发 input 选中.
加一点样式
- .btn>span:after{
- /** 换一下选择器 **/
- }
- .btn>input[type=checkbox]{
- display: none
- }
- .btn>input[type=checkbox]:checked+span:after{
- animation: ripple 1s;
- }
这样也能触发动画, 但问题是, 当再次点击的时候就成了非选中状态了, 怎么触发动画呢?
其实可以用: not 来实现
- .btn>input[type=checkbox]:not(:checked)+span:after{
- animation: ripple 1s;
- }
乍一看好像挺聪明的, 仔细一想, 正反两个都写了动画, 不就跟: checked 没关系了? 还不如直接
- .btn>input[type=checkbox]+span:after{
- animation: ripple 1s;
- }
无限轮回中...
这个问题困扰了我好久, 不过皇天不负有心人, 后来试着在两种状态下触发不同的动画是可以分别触发的, 如下
- .btn>input[type=checkbox]:checked+span:after{
- animation: ripple1 1s;
- }
- .btn>input[type=checkbox]:not(:checked)+span:after{
- animation: ripple2 1s;
- }
这个应该很好理解吧.
那么, 重点来了, 现在把动画 ripple1 和 ripple2 里面的动画过程都改成一样, 也是可以分别触发的, 也就是说, 只要动画名称不一样, CSS 都会当成不同的动画来处理
这样就简单了, 我们只需要默认一个状态, 选中一个状态, 然后分别触发名称不同的动画就行了~
- .btn>input[type=checkbox]+span:after{
- animation: ripple-in 1s;
- }
- .btn>input[type=checkbox]:checked+span:after{
- animation: ripple-out 1s;
- }
- @keyframes ripple-in{
- from {
- transform:translate(-50%,-50%) scale(0);
- background: rgba(0,0,0,.25);
- }
- to {
- transform:translate(-50%,-50%) scale(1);
- background: transparent;
- }
- }
- @keyframes ripple-out{/* 仅仅名称不同 */
- from {
- transform:translate(-50%,-50%) scale(0);
- background: rgba(0,0,0,.25);
- }
- to {
- transform:translate(-50%,-50%) scale(1);
- background: transparent;
- }
- }
效果就如文章一开始所示, 完美
完整 demo 如下
https://codepen.io/xboxyan/pen/Jmvyex/
一些不足
由于上述动画样式在默认情况下就会被触发, 所以页面加载进来就会看到按钮上的水滴动画运动一次, 不过也不是特别明显, 还可以接受.
其次, 实际效果肯定是希望鼠标点击哪里, 就以该点为中心扩散, 我们 CSS 肯定是做不到这点的, 只能从中心扩散, 这也只能妥协了. 这里提供一个思路, 可以使用 CSS 的变量, 每次点击的时候吧相应的值存在 style 里面, 这样 CSS 中也能用上.
希望能用 CSS 今后挖掘出更多有趣的效果 ^ ^
更多 web 前端开发 https://www.html.cn/ 知识, 请查阅 HTML 中文网 !!
来源: http://www.css88.com/web/css/16163.html