基於CSS實現MaterialUI按鈕點選動畫並封裝成 React 元件
前言
作為一個前端框架的重度使用者,在技術選型上也會非常注意其生態和完整性.筆者先後開發過基於,react,angular等框架的專案,碧如vue生態的elementUI,ant-design-vue,iView等成熟的UI框架,react生態的ant-design,materialUI等,這些第三方UI框架極大的降低了我們開發一個專案的成本和複雜度,使開發者更專注於實現業務邏輯和服務化.
但隨著對使用者體驗的越來越重視,對互動體驗要求的提高以及3等新標準的出現,使得web更加大放異彩,各種動效的實現都變得非常容易.筆者在研究materialUI框架時對於它的互動及其讚歎.所以為了自己能實現一個類似materialUI的按鈕點選動畫,並封裝到自己的UI庫中,筆者特地總結了一些思路,希望可以和廣大的前端工程師們一起探討.
正文
首先我們看一下materialUI的按鈕點選效果:
本質上也是用了css3動畫的特性,筆者檢視原始碼和通過點擊發現materialUI會根據點選位置不同而作不同位置的動畫,這個有點意思.我們先不講這麼複雜的例子,下面通過css3的方案來實現一個類似的效果.筆者實現的效果如下:
上圖已經是筆者基於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-positiovJrRQGFjFn: 50%; transform: scale(12,12); opacity: 0; transition: transform .6s cubic-bezvJrRQGFjFier(.75,.23,.43,.82),opacity .6s; } &:active::after { transform: scale(0,0); opacity: .5; } }
以上程式碼就是通過設定transform的scale以及透明度,並且設定一個漸變的徑向背景影象來實現水波紋動畫的為了實現更優雅的動畫,上面的css動畫的實現可以藉助cubic-bezier這個線上工具,他可以生成各種不同形式的貝塞爾曲線.工具長這樣:
2. 元件設計思路
僅僅用上述程式碼雖然可以實現一個按鈕點選的動畫效果,但是並不通用,也不符合作為一個經驗豐富的程式設計師的風格,所以接下來我們要一步步把它封裝成一個通用的按鈕元件,讓它無所不用.
元件的設計思路我這裡參考ant-design的模式,基於開閉原則,我們知道一個可擴充套件的按鈕元件一般都具備如下特點:
- 允許使用者修改按鈕樣式
- 對外暴露按鈕事件方法
- 提供按鈕主題和外形配置
- 可插拔,可組合 基於以上幾點,我們來設計這個react元件.
3. 基於react和css3的button元件具體vJrRQGFjF實現
首先,我們的元件是採用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的部分,也是元件設計的核心,按鈕元件對外暴露了onCpck,block這幾個props,className用於修改元件類名以便控制組件樣式,type主要是控制組件的風格,類似於antd的primary等樣式,shape用來控制是否是圓形按鈕還是圓角按鈕,block用來控制按鈕是否是塊.具體形式如下:
經過優化後的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.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,transparent 11%); background-repeat: no-repeat; background-position: 50%; transform: scale(12,12); opacity: 0; transition: transform .6s,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版的按鈕元件或者一個angular版的元件,變得只是語法而已.這樣的元件設計思路和元素被官方用在很多ui庫中,比如單一職責原理,元件的開閉原則,去中心,可組合等,希望對大家今後設計元件有所幫助。
到此這篇關於純 CSS 打造類 MaterialUI 的按鈕點選動畫並封裝成 React 元件的文章就介紹到這了,更多相關css MaterialUI 按鈕點選動畫內容請搜尋我們以前的文章或繼續瀏覽下面的相關文章希望大家以後多多支援我們!