《精通react/vue组件设计》之用纯css打造类materialUI的按钮点击动画并封装成react组件

徐小夕 等级 669 0 0
标签: 前端

前言

作为一个前端框架的重度使用者,在技术选型上也会非常注意其生态和完整性.笔者先后开发过基于vue,react,angular等框架的项目,碧如vue生态的elementUI, ant-design-vue, iView等成熟的UI框架, react生态的ant-design, materialUI等,这些第三方UI框架极大的降低了我们开发一个项目的成本和复杂度,使开发者更专注于实现业务逻辑和服务化.

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

正文

首先我们看一下materialUI的按钮点击效果: 《精通react/vue组件设计》之用纯css打造类materialUI的按钮点击动画并封装成react组件 本质上也是用了css3动画的特性, 笔者查看源代码和通过点击发现materialUI会根据点击位置不同而作不同位置的动画,这个有点意思.我们先不讲这么复杂的例子,下面通过css3的方案来实现一个类似的效果.笔者实现的效果如下: 《精通react/vue组件设计》之用纯css打造类materialUI的按钮点击动画并封装成react组件 上图已经是笔者基于react封装好的一个按钮Button组件,那么我们就先一步步实现它吧.

1. 原理

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

.xButton {
  position: relative;
  overflow: hidden;
  display: inline-block;
  padding: 6px 1em;
  border-radius: 4px;
  color: #fff;
  background-color: #000;
  user-select:none;   // 禁止用户选中
  cursor: pointer;
}

.ripple {
  &::after {
    content: "";
    display: block;
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    background-image: radial-gradient(circle, #fff 10%, transparent 11%);
    background-repeat: no-repeat;
    background-position: 50%;
    transform: scale(12, 12);
    opacity: 0;
    transition: transform .6s cubic-bezier(.75,.23,.43,.82), opacity .6s;
  }
  &:active::after {
    transform: scale(0, 0);
    opacity: .5;
  }
}

以上代码就是通过设置transform的scale以及透明度, 并且设置一个渐变的径向背景图像来实现水波纹动画的为了实现更优雅的动画,上面的css动画的实现可以借助cubic-bezier这个在线工具,他可以生成各种不同形式的贝塞尔曲线.工具长这样: 《精通react/vue组件设计》之用纯css打造类materialUI的按钮点击动画并封装成react组件

2. 组件设计思路

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

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

  • 允许用户修改按钮样式
  • 对外暴露按钮事件方法
  • 提供按钮主题和外形配置
  • 可插拔,可组合 基于以上几点,我们来设计这个react组件.

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

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

import classnames from 'classnames'
import styles from './index.less'

/**
 * @param {onClick} func 对外暴露的点击事件
 * @param {className} string 自定义类名
 * @param {type} string 按钮类型 primary | warning | info | default | pure
 * @param {shape} string 按钮形状 circle | radius(默认)
 * @param {block} boolean 按钮展示 true | false(默认)
 */
export default function Button(props) {
  let { children, onClick, className, type, shape, block } = props
  return <div 
            className={classnames(styles.xButton, styles.ripple, styles[type], styles[shape], block ? styles.block : '', className)}
            onClick={onClick}
        >
            { children }
        </div>
}

这是button的js部分,也是组件设计的核心, 按钮组件对外暴露了onClick, className, type, shape, block这几个props, className用于修改组件类名以便控制组件样式, type主要是控制组件的风格, 类似于antd的primary等样式, shape用来控制是否是圆形按钮还是圆角按钮, block用来控制按钮是否是块.具体形式如下:

《精通react/vue组件设计》之用纯css打造类materialUI的按钮点击动画并封装成react组件 经过优化后的css长这样:

.xButton {
  box-sizing: border-box;
  display: inline-block;
  padding: 6px 1em;
  border-radius: 4px;
  color: #fff;
  font-family: inherit;
  background-color: #000;
  user-select:none;   // 禁止用户选中
  cursor: pointer;
  text-align: center;
  &.primary {
    background-color: #09f;
  }
  &.warning {
    background-color: #F90;
  }
  &.info {
    background-color: #C03;
  }
  &.pure {
    border: 1px solid #ccc;
    color: rgba(0, 0, 0, 0.65);
    background-color: #fff;
    &::after {
      background-image: radial-gradient(circle, #ccc 10%, transparent 11%);
    }
  }

  // 形状
  &.circle {
    border-radius: 1.5em;
  }

  // 适应其父元素
  &.block {
    // width: 100%;
    display: block;
  }
}

.ripple {
  position: relative;
  overflow: hidden;
  &::after {
    content: "";
    display: block;
    position: absolute;
    width: 100%;
    height: 100%;
    top: 0;
    left: 0;
    pointer-events: none;
    background-image: radial-gradient(circle, #fff 10%, transparent 11%);
    background-repeat: no-repeat;
    background-position: 50%;
    transform: scale(12, 12);
    opacity: 0;
    transition: transform .6s, opacity .6s;
  }
  &:active::after {
    transform: scale(0, 0);
    opacity: .3;
    //设置初始状态
    transition: 0s;
  }
}

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

// index.js
import { Button } from '@/components'
import styles from './index.css'
export default function() {
  return (
    <div className={styles.normal}>
      <Button className={styles.btn}>default</Button>
      <Button className={styles.btn} type="warning">warning</Button>
      <Button className={styles.btn} type="primary">primary</Button>
      <Button className={styles.btn} type="info">info</Button>
      <Button className={styles.btn} type="pure">pure</Button>
      <Button className={styles.btn} type="primary" shape="circle">circle</Button>
      <Button className={styles.mb16} type="primary" block>primary&block</Button>
      <Button type="warning" shape="circle" block onClick={() => { alert('block')}}>circle&block</Button>
    </div>
  )
}

之前我们看到的按钮样式就是通过如上代码生成的,是不是很简单呢? 来我们再次看看点击的动效:

《精通react/vue组件设计》之用纯css打造类materialUI的按钮点击动画并封装成react组件 其实不仅仅是react, 我们使用同样的原理也可以实现一个vue版的按钮组件或者一个angular版的组件,变得只是语法而已.这样的组件设计思路和元素被官方用在很多ui库中, 比如单一职责原理, 组件的开闭原则, 去中心,可组合等,希望对大家今后设计组件有所帮助.

最后

如果想了解本文完整的思维导图, 更多H5游戏, webpacknodegulpcss3javascriptnodeJScanvas数据可视化等前端知识和实战,欢迎在公号《趣谈前端》加入我们一起学习讨论,共同探索前端的边界。

《精通react/vue组件设计》之用纯css打造类materialUI的按钮点击动画并封装成react组件

更多推荐

收藏
评论区

相关推荐

React Hooks 快速上手
React Hook 快速上手 一、 Hook 简介 1.1 Hook历史 在React Hook出现之前的版本中,组件主要分为两种:函数式组件和类组件。其中,函数式组件通常只考虑负责UI的渲染,没有自身的状态也没有业务逻辑代码,是一个纯函数。而类组件则不同,类组件有自己的内部
《精通react/vue组件设计》之用纯css打造类materialUI的按钮点击动画并封装成react组件
前言 作为一个前端框架的重度使用者,在技术选型上也会非常注意其生态和完整性.笔者先后开发过基于vue,react,angular等框架的项目,碧如vue生态的elementUI, antdesignvue, iView等成熟的UI框架, react生态的antdesign, materialUI等,这些第三方UI框架极大的降低了我们开发一个项目的成本和
轻松使用纯css3打造有点意思的故障艺术(附React/Vue加强组件版)
前言 很早之前就看到国外很多酷炫的网站在实践"故障艺术", 或者错位动画", 感觉非常有意思, 现在APP端的抖音启动界面有着这种设计的影子, 作为一名用于探索未知的前端工程师, 有必要好好实践一下这一设计. 正文 接下来笔者将带大家使用纯Css3来实现"故障动画", 并将这一特效封装成React/vue组件, 供大家学习和使用. 先来看看实现的效果:
CSS Modules 解决 react 项目 css 样式互相影响的问题
CSS Modules 解决 react 项目 css 样式互相影响的问题 CSS Modules 解决 react 项目 css 样式互相影响的问题 (http
Taro 入门教程
简介 Taro 是一个遵循 React 语法规范的开放式跨端跨框架解决方案,支持使用 React/Vue/Nerv 等框架来开发微信/京东/百度/
新手学习 React 迷惑的点
网上各种言论说 React 上手比 Vue 难,可能难就难不能深刻理解 JSX,或者对 ES6 的一些特性理解得不够深刻,导致觉得有些点难以理解,然后说 React 比较难上手,还反人类啥的,所以我打算写两篇文章来讲新手学习 React 的时候容易迷惑的点写出来,如果你还以其他的对于学习 React 很迷惑的点,可以在留言区里给我留言。为什么要引入 Reac
项目中的富文本编辑器该如何选择?
项目中经常需要用到富文本编辑器的时候,而常见的富文本编辑器都有哪些?该如何选择?先看看市面上都有哪些可用的富文本编辑器: (插件式的,支持 Vue,React,Angular 框架) (Typescript 开发的 Web 富文本编辑器, 轻量、简洁、易用、开源免费,支持 JS 直接引入使用,或者 Vue2/3,React) (开源,插件多,功能齐全,支持
Angular React Vue我应该选择什么?
2017 年比较 Angular、React、Vue 三剑客 ============================== 为 web 应用选择 JavaScript 开发框架是一件很费脑筋的事。现如今 [Angular](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Flink.juej
React Hooks究竟是什么呢?
**摘要:** React Hooks原理解析。 * 原文:[快速了解 React Hooks 原理](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fsegmentfault.com%2Fa%2F1190000019966124) * 译者:前端小智 我们大部分 React 类
React 表格组件 GridManager
GridManager React ================= \> 基于 React 的 GridManager 封装, 用于便捷的在 React 中使用GridManager. 除过React特性外,其它API与GridManager API相同。 ![image](https://s2.ax1x.com/2019/04/16/AxA4xK.
React官方团队推出了最新的 React Server Components 技术
最近react个官方团队推出了最新的 React Server Components 这项技术。 这篇文章将对其相关知识点进行介绍。 那些常见的渲染模式 ========= CSR --- 客户端渲染(Client Side Rendering) 应该是前端最熟悉的一种模式了。从前端的发展历程上看,富客户端目前也已经成为现代前端应用的主流架构。从jQu
React实战之React+Redux实现一个天气预报小项目
![](https://oscimg.oschina.net/oscnet/355a9b3e0af9e3410d9cf918fdfe69b2379.jpg)**引言** ------------------------------------------------------------------------------------ 经过一段时间的Re
React技术栈实现XX点评电商App
> 项目地址:[https://github.com/Nealyang/React-Fullstack-Dianping-Demo](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Fgithub.com%2FNealyang%2FReact-Fullstack-Dianping-Demo)
React的Sass配置
React提供的脚手架[creact-react-app](https://www.oschina.net/action/GoToLink?url=https%3A%2F%2Ffacebook.github.io%2Fcreate-react-app%2Fdocs%2Fadding-a-sass-stylesheet)创建的工程文件不像vue那种暴露出web
storybook配置之基本配置和webpack配置
#默认配置 Storybook有一个默认的适合(suits)大型项目开发的webpack配置,假如你使用react app,他类似于创建一个react app的配置,并经过调整(tweaked ),使其与vue cli的webpack配置非常相似 开始学习Storybook配置 学习内容(Table of Contents) - Babel ES2016+