最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

基于CSS實(shí)現(xiàn)MaterialUI按鈕點(diǎn)擊動(dòng)畫并封裝成 React 組件

 更新時(shí)間:2021年11月09日 11:19:52   作者:徐小夕  
筆者先后開發(fā)過(guò)基于vue,react,angular等框架的項(xiàng)目,碧如vue生態(tài)的elementUI, ant-design-vue, iView等成熟的UI框架, react生態(tài)的ant-design, materialUI等,這些第三方UI框架極大的降低了我們開發(fā)一個(gè)項(xiàng)目的成本和復(fù)雜度,使開發(fā)者更專注于實(shí)現(xiàn)業(yè)務(wù)邏輯和服務(wù)化

前言

作為一個(gè)前端框架的重度使用者,在技術(shù)選型上也會(huì)非常注意其生態(tài)和完整性.筆者先后開發(fā)過(guò)基于vue,react,angular等框架的項(xiàng)目,碧如vue生態(tài)的elementUI, ant-design-vue, iView等成熟的UI框架, react生態(tài)的ant-design, materialUI等,這些第三方UI框架極大的降低了我們開發(fā)一個(gè)項(xiàng)目的成本和復(fù)雜度,使開發(fā)者更專注于實(shí)現(xiàn)業(yè)務(wù)邏輯和服務(wù)化.

但隨著對(duì)用戶體驗(yàn)的越來(lái)越重視,對(duì)交互體驗(yàn)要求的提高以及css3等新標(biāo)準(zhǔn)的出現(xiàn),使得web更加大放異彩, 各種動(dòng)效的實(shí)現(xiàn)都變得非常容易.筆者在研究materialUI框架時(shí)對(duì)于它的交互及其贊嘆.所以為了自己能實(shí)現(xiàn)一個(gè)類似materialUI的按鈕點(diǎn)擊動(dòng)畫,并封裝到自己的UI庫(kù)中,筆者特地總結(jié)了一些思路,希望可以和廣大的前端工程師們一起探討.

正文

首先我們看一下materialUI的按鈕點(diǎn)擊效果:

本質(zhì)上也是用了css3動(dòng)畫的特性, 筆者查看源代碼和通過(guò)點(diǎn)擊發(fā)現(xiàn)materialUI會(huì)根據(jù)點(diǎn)擊位置不同而作不同位置的動(dòng)畫,這個(gè)有點(diǎn)意思.我們先不講這么復(fù)雜的例子,下面通過(guò)css3的方案來(lái)實(shí)現(xiàn)一個(gè)類似的效果.筆者實(shí)現(xiàn)的效果如下:

上圖已經(jīng)是筆者基于react封裝好的一個(gè)按鈕Button組件,那么我們就先一步步實(shí)現(xiàn)它吧.

1. 原理

這個(gè)動(dòng)效的原理其實(shí)也很簡(jiǎn)單,就是利用css3的transition過(guò)渡動(dòng)畫,配合::after偽對(duì)象就可以實(shí)現(xiàn),點(diǎn)擊的時(shí)候由于元素會(huì)激活:active偽類, 然后我們基于這個(gè)偽類, 在::after偽對(duì)象上做背景的動(dòng)畫即可. 偽代碼如下:

.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; 
  } 
} 

以上代碼就是通過(guò)設(shè)置transform的scale以及透明度, 并且設(shè)置一個(gè)漸變的徑向背景圖像來(lái)實(shí)現(xiàn)水波紋動(dòng)畫的為了實(shí)現(xiàn)更優(yōu)雅的動(dòng)畫,上面的css動(dòng)畫的實(shí)現(xiàn)可以借助cubic-bezier這個(gè)在線工具,他可以生成各種不同形式的貝塞爾曲線.工具長(zhǎng)這樣:

2. 組件設(shè)計(jì)思路

僅僅用上述代碼雖然可以實(shí)現(xiàn)一個(gè)按鈕點(diǎn)擊的動(dòng)畫效果,但是并不通用, 也不符合作為一個(gè)經(jīng)驗(yàn)豐富的程序員的風(fēng)格,所以接下來(lái)我們要一步步把它封裝成一個(gè)通用的按鈕組件,讓它無(wú)所不用.

組件的設(shè)計(jì)思路我這里參考ant-design的模式, 基于開閉原則,我們知道一個(gè)可擴(kuò)展的按鈕組件一般都具備如下特點(diǎn):

  • 允許用戶修改按鈕樣式
  • 對(duì)外暴露按鈕事件方法
  • 提供按鈕主題和外形配置
  • 可插拔,可組合 基于以上幾點(diǎn),我們來(lái)設(shè)計(jì)這個(gè)react組件.

3. 基于react和css3的button組件具體實(shí)現(xiàn)

首先,我們的組件是采用react實(shí)現(xiàn), 技術(shù)點(diǎn)我會(huì)采用比較流行的umi腳手架, classnames庫(kù)以及css Module, 代碼很簡(jiǎn)單, 我們來(lái)看看吧.

import classnames from 'classnames' 
import styles from './index.less' 
 
/** 
 * @param {onClick} func 對(duì)外暴露的點(diǎn)擊事件 
 * @param {className} string 自定義類名 
 * @param {type} string 按鈕類型 primary | warning | info | default | pure 
 * @param {shape} string 按鈕形狀 circle | radius(默認(rèn)) 
 * @param {block} boolean 按鈕展示 true | false(默認(rèn)) 
 */ 
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部分,也是組件設(shè)計(jì)的核心, 按鈕組件對(duì)外暴露了onCpck, className, type, shape, block這幾個(gè)props, className用于修改組件類名以便控制組件樣式, type主要是控制組件的風(fēng)格, 類似于antd的primary等樣式, shape用來(lái)控制是否是圓形按鈕還是圓角按鈕, block用來(lái)控制按鈕是否是塊.具體形式如下:

經(jīng)過(guò)優(yōu)化后的css長(zhǎng)這樣:

.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; 
  } 
 
  // 適應(yīng)其父元素 
  &.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; 
    //設(shè)置初始狀態(tài) 
    transition: 0s; 
  } 
} 

我們實(shí)現(xiàn)按鈕樣式的切換完全是用css module帶來(lái)的高靈活性, 使其讓屬性和類名高度關(guān)聯(lián). 接下來(lái)看看我們?nèi)绾问褂冒桑?/p>

// 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> 
  ) 
} 

之前我們看到的按鈕樣式就是通過(guò)如上代碼生成的,是不是很簡(jiǎn)單呢? 來(lái)我們?cè)俅慰纯袋c(diǎn)擊的動(dòng)效:

其實(shí)不僅僅是react, 我們使用同樣的原理也可以實(shí)現(xiàn)一個(gè)vue版的按鈕組件或者一個(gè)angular版的組件,變得只是語(yǔ)法而已.這樣的組件設(shè)計(jì)思路和元素被官方用在很多ui庫(kù)中, 比如單一職責(zé)原理, 組件的開閉原則, 去中心,可組合等,希望對(duì)大家今后設(shè)計(jì)組件有所幫助。

到此這篇關(guān)于純 CSS 打造類 MaterialUI 的按鈕點(diǎn)擊動(dòng)畫并封裝成 React 組件的文章就介紹到這了,更多相關(guān)css MaterialUI 按鈕點(diǎn)擊動(dòng)畫內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • React冒泡和阻止冒泡的應(yīng)用詳解

    React冒泡和阻止冒泡的應(yīng)用詳解

    這篇文章主要介紹了React冒泡和阻止冒泡的應(yīng)用詳解,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2020-08-08
  • React中的refs的使用教程

    React中的refs的使用教程

    本篇文章主要介紹了React中的refs的使用教程,小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-02-02
  • react navigation中點(diǎn)擊底部tab怎么傳遞參數(shù)

    react navigation中點(diǎn)擊底部tab怎么傳遞參數(shù)

    本文主要介紹了react navigation中點(diǎn)擊底部tab怎么傳遞參數(shù),文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-04-04
  • react中useEffect Hook作用小結(jié)

    react中useEffect Hook作用小結(jié)

    React中useEffect是一個(gè)非常重要的Hook,它允許我們函數(shù)組件中執(zhí)行副作用操作,本文就來(lái)介紹一下useEffect Hook作用,具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-11-11
  • 自己動(dòng)手封裝一個(gè)React Native多級(jí)聯(lián)動(dòng)

    自己動(dòng)手封裝一個(gè)React Native多級(jí)聯(lián)動(dòng)

    這篇文章主要介紹了自己動(dòng)手封裝一個(gè)React Native多級(jí)聯(lián)動(dòng),小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧
    2018-09-09
  • react分頁(yè)顯示數(shù)據(jù)的方法

    react分頁(yè)顯示數(shù)據(jù)的方法

    分頁(yè)在很多地方都可以用到,本文主要實(shí)現(xiàn)了react分頁(yè)顯示,主要使用三個(gè)組件,父組件listBox、列表組件List、按鈕組件PageButton,感興趣的可以了解一下
    2021-08-08
  • react將文件轉(zhuǎn)為base64上傳的示例代碼

    react將文件轉(zhuǎn)為base64上傳的示例代碼

    本文主要介紹了react將文件轉(zhuǎn)為base64上傳的示例代碼,文中通過(guò)示例代碼介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧
    2023-09-09
  • React閉包陷阱產(chǎn)生和解決小結(jié)

    React閉包陷阱產(chǎn)生和解決小結(jié)

    閉包陷阱是一個(gè)常見(jiàn)的問(wèn)題,尤其是在處理異步操作、事件處理器、或是定時(shí)器時(shí),本文就來(lái)介紹一下React閉包陷阱產(chǎn)生和解決小結(jié),具有一定的參考價(jià)值,感興趣的可以了解一下
    2025-04-04
  • useEvent顯著降低Hooks負(fù)擔(dān)的原生Hook

    useEvent顯著降低Hooks負(fù)擔(dān)的原生Hook

    這篇文章主要為大家介紹了useEvent顯著降低Hooks負(fù)擔(dān)的原生Hook示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07
  • 列表頁(yè)常見(jiàn)hook封裝實(shí)例

    列表頁(yè)常見(jiàn)hook封裝實(shí)例

    這篇文章主要為大家介紹了列表頁(yè)常見(jiàn)的hook封裝示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-07-07

最新評(píng)論

筠连县| 云龙县| 宝兴县| 柘荣县| 定陶县| 盖州市| 凤阳县| 南部县| 郑州市| 洮南市| 中超| 穆棱市| 五寨县| 务川| 巴南区| 兴安县| 台山市| 云和县| 调兵山市| 广平县| 凭祥市| 定襄县| 江川县| 湖口县| 文安县| 南丹县| 哈尔滨市| 晋中市| 青川县| 涞源县| 保靖县| 安塞县| 安泽县| 永嘉县| 朝阳区| 衡南县| 陇南市| 滦南县| 朝阳县| 泗阳县| 龙州县|