文章详情

短信预约-IT技能 免费直播动态提醒

请输入下面的图形验证码

提交验证

短信预约提醒成功

如何用纯 CSS 打造类 MaterialUI 的按钮点击动画并封装成 React 组件

2024-12-02 17:53

关注

但随着对用户体验的越来越重视,对交互体验要求的提高以及css3等新标准的出现,使得web更加大放异彩, 各种动效的实现都变得非常容易.笔者在研究materialUI框架时对于它的交互及其赞叹.所以为了自己能实现一个类似materialUI的按钮点击动画,并封装到自己的UI库中,笔者特地总结了一些思路,希望可以和广大的前端工程师们一起探讨.

正文

首先我们看一下materialUI的按钮点击效果:

本质上也是用了css3动画的特性, 笔者查看源代码和通过点击发现materialUI会根据点击位置不同而作不同位置的动画,这个有点意思.我们先不讲这么复杂的例子,下面通过css3的方案来实现一个类似的效果.笔者实现的效果如下:

上图已经是笔者基于react封装好的一个按钮Button组件,那么我们就先一步步实现它吧.

1. 原理

这个动效的原理其实也很简单,就是利用css3的transition过渡动画,配合::after伪对象就可以实现,点击的时候由于元素会激活:active伪类, 然后我们基于这个伪类, 在::after伪对象上做背景的动画即可. 伪代码如下:

  1. .xButton { 
  2.   position: relative
  3.   overflow: hidden; 
  4.   display: inline-block; 
  5.   padding: 6px 1em; 
  6.   border-radius: 4px; 
  7.   color: #fff; 
  8.   background-color: #000; 
  9.   user-select:none;   // 禁止用户选中 
  10.   cursor: pointer; 
  11.  
  12. .ripple { 
  13.   &::after { 
  14.     content: ""
  15.     display: block; 
  16.     position: absolute
  17.     width: 100%; 
  18.     height: 100%; 
  19.     top: 0; 
  20.     left: 0; 
  21.     background-image: radial-gradient(circle, #fff 10%, transparent 11%); 
  22.     background-repeat: no-repeat; 
  23.     background-position: 50%; 
  24.     transform: scale(12, 12); 
  25.     opacity: 0; 
  26.     transition: transform .6s cubic-bezier(.75,.23,.43,.82), opacity .6s; 
  27.   } 
  28.   &:active::after { 
  29.     transform: scale(0, 0); 
  30.     opacity: .5; 
  31.   } 

以上代码就是通过设置transform的scale以及透明度, 并且设置一个渐变的径向背景图像来实现水波纹动画的为了实现更优雅的动画,上面的css动画的实现可以借助cubic-bezier这个在线工具,他可以生成各种不同形式的贝塞尔曲线.工具长这样:

2. 组件设计思路

仅仅用上述代码虽然可以实现一个按钮点击的动画效果,但是并不通用, 也不符合作为一个经验丰富的程序员的风格,所以接下来我们要一步步把它封装成一个通用的按钮组件,让它无所不用.

组件的设计思路我这里参考ant-design的模式, 基于开闭原则,我们知道一个可扩展的按钮组件一般都具备如下特点:

3. 基于react和css3的button组件具体实现

首先,我们的组件是采用react实现, 技术点我会采用比较流行的umi脚手架, classnames库以及css Module, 代码很简单, 我们来看看吧.

  1. import classnames from 'classnames' 
  2. import styles from './index.less' 
  3.  
  4.  
  5. export default function Button(props) { 
  6.   let { children, onClick, className, type, shape, block } = props 
  7.   return 
  8.             className={classnames(styles.xButton, styles.ripple, styles[type], styles[shape], block ? styles.block : '', className)} 
  9.             onClick={onClick} 
  10.         > 
  11.             { children } 
  12.         
 
  • 这是button的js部分,也是组件设计的核心, 按钮组件对外暴露了onClick, className, type, shape, block这几个props, className用于修改组件类名以便控制组件样式, type主要是控制组件的风格, 类似于antd的primary等样式, shape用来控制是否是圆形按钮还是圆角按钮, block用来控制按钮是否是块.具体形式如下:

    经过优化后的css长这样:

    1. .xButton { 
    2.   box-sizing: border-box; 
    3.   display: inline-block; 
    4.   padding: 6px 1em; 
    5.   border-radius: 4px; 
    6.   color: #fff; 
    7.   font-family: inherit; 
    8.   background-color: #000; 
    9.   user-select:none;   // 禁止用户选中 
    10.   cursor: pointer; 
    11.   text-align: center; 
    12.   &.primary { 
    13.     background-color: #09f; 
    14.   } 
    15.   &.warning { 
    16.     background-color: #F90; 
    17.   } 
    18.   &.info { 
    19.     background-color: #C03; 
    20.   } 
    21.   &.pure { 
    22.     border: 1px solid #ccc; 
    23.     color: rgba(0, 0, 0, 0.65); 
    24.     background-color: #fff; 
    25.     &::after { 
    26.       background-image: radial-gradient(circle, #ccc 10%, transparent 11%); 
    27.     } 
    28.   } 
    29.  
    30.   // 形状 
    31.   &.circle { 
    32.     border-radius: 1.5em; 
    33.   } 
    34.  
    35.   // 适应其父元素 
    36.   &.block { 
    37.     // width: 100%; 
    38.     display: block; 
    39.   } 
    40.  
    41. .ripple { 
    42.   position: relative
    43.   overflow: hidden; 
    44.   &::after { 
    45.     content: ""
    46.     display: block; 
    47.     position: absolute
    48.     width: 100%; 
    49.     height: 100%; 
    50.     top: 0; 
    51.     left: 0; 
    52.     pointer-events: none; 
    53.     background-image: radial-gradient(circle, #fff 10%, transparent 11%); 
    54.     background-repeat: no-repeat; 
    55.     background-position: 50%; 
    56.     transform: scale(12, 12); 
    57.     opacity: 0; 
    58.     transition: transform .6s, opacity .6s; 
    59.   } 
    60.   &:active::after { 
    61.     transform: scale(0, 0); 
    62.     opacity: .3; 
    63.     //设置初始状态 
    64.     transition: 0s; 
    65.   } 
    66. 复制代码 

    我们实现按钮样式的切换完全是用css module带来的高灵活性, 使其让属性和类名高度关联. 接下来看看我们如何使用吧!

    1. // index.js 
    2. import { Button } from '@/components' 
    3. import styles from './index.css' 
    4. export default function() { 
    5.   return ( 
    6.      
    7.       default 
    8.       "warning">warning 
    9.       "primary">primary 
    10.       "info">info 
    11.       "pure">pure 
    12.       "primary" shape="circle">circle 
    13.       "primary" block>primary&block 
    14.       "warning" shape="circle" block onClick={() => { alert('block')}}>circle&block 
    15.     
     
  •   ) 
  • 之前我们看到的按钮样式就是通过如上代码生成的,是不是很简单呢? 来我们再次看看点击的动效:

    其实不仅仅是react, 我们使用同样的原理也可以实现一个vue版的按钮组件或者一个angular版的组件,变得只是语法而已.这样的组件设计思路和元素被官方用在很多ui库中, 比如单一职责原理, 组件的开闭原则, 去中心,可组合等,希望对大家今后设计组件有所帮助。

    本文转载自微信公众号「趣谈前端」,可以通过以下二维码关注。转载本文请联系趣谈前端公众号。

     

    来源:趣谈前端内容投诉

    免责声明:

    ① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。

    ② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341

    软考中级精品资料免费领

    • 2024年上半年信息系统项目管理师第二批次真题及答案解析(完整版)

      难度     813人已做
      查看
    • 【考后总结】2024年5月26日信息系统项目管理师第2批次考情分析

      难度     354人已做
      查看
    • 【考后总结】2024年5月25日信息系统项目管理师第1批次考情分析

      难度     318人已做
      查看
    • 2024年上半年软考高项第一、二批次真题考点汇总(完整版)

      难度     435人已做
      查看
    • 2024年上半年系统架构设计师考试综合知识真题

      难度     224人已做
      查看

    相关文章

    发现更多好内容

    猜你喜欢

    AI推送时光机
    位置:首页-资讯-后端开发
    咦!没有更多了?去看看其它编程学习网 内容吧
    首页课程
    资料下载
    问答资讯