做爲一個前端框架的重度使用者,在技術選型上也會很是注意其生態和完整性.筆者前後開發過基於vue,react,angular等框架的項目,碧如vue生態的elementUI, ant-design-vue, iView等成熟的UI框架, react生態的ant-design, materialUI等,這些第三方UI框架極大的下降了咱們開發一個項目的成本和複雜度,使開發者更專一於實現業務邏輯和服務化.javascript
但隨着對用戶體驗的愈來愈重視,對交互體驗要求的提升以及css3等新標準的出現,使得web更加大放異彩, 各類動效的實現都變得很是容易.筆者在研究materialUI框架時對於它的交互及其讚歎.因此爲了本身能實現一個相似materialUI的按鈕點擊動畫,並封裝到本身的UI庫中,筆者特意總結了一些思路,但願能夠和廣大的前端工程師們一塊兒探討.css
首先咱們看一下materialUI的按鈕點擊效果: 前端
這個動效的原理其實也很簡單,就是利用css3的transition過渡動畫,配合::after僞對象就能夠實現,點擊的時候因爲元素會激活:active僞類, 而後咱們基於這個僞類, 在::after僞對象上作背景的動畫便可. 僞代碼以下:vue
.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這個在線工具,他能夠生成各類不一樣形式的貝塞爾曲線.工具長這樣: java
僅僅用上述代碼雖然能夠實現一個按鈕點擊的動畫效果,可是並不通用, 也不符合做爲一個經驗豐富的程序員的風格,因此接下來咱們要一步步把它封裝成一個通用的按鈕組件,讓它無所不用.node
組件的設計思路我這裏參考ant-design的模式, 基於開閉原則,咱們知道一個可擴展的按鈕組件通常都具有以下特色:react
首先,咱們的組件是採用react實現, 技術點我會採用比較流行的umi腳手架, classnames庫以及css Module, 代碼很簡單, 咱們來看看吧.webpack
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用來控制按鈕是不是塊.具體形式以下:css3
.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>
)
}
複製代碼
以前咱們看到的按鈕樣式就是經過如上代碼生成的,是否是很簡單呢? 來咱們再次看看點擊的動效:
若是想了解本文完整的思惟導圖, 更多H5遊戲, webpack,node,gulp,css3,javascript,nodeJS,canvas數據可視化等前端知識和實戰,歡迎在公號《趣談前端》加入咱們一塊兒學習討論,共同探索前端的邊界。