日本综合一区二区|亚洲中文天堂综合|日韩欧美自拍一区|男女精品天堂一区|欧美自拍第6页亚洲成人精品一区|亚洲黄色天堂一区二区成人|超碰91偷拍第一页|日韩av夜夜嗨中文字幕|久久蜜综合视频官网|精美人妻一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時間:8:30-17:00
你可能遇到了下面的問題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營銷解決方案
如何使用vue開發(fā)波紋點(diǎn)擊特效組件

最近在使用 vue2 做一個新的 material ui 庫,波紋點(diǎn)擊效果在 material design 中被多次使用到,于是決定把它封裝成一個公共的組件,使用時直接調(diào)用就好啦。

開發(fā)之前的思考

常見的波紋點(diǎn)擊效果的實(shí)現(xiàn)方式是監(jiān)聽元素的 mousedown 事件,在元素內(nèi)部創(chuàng)建一個 波紋元素 ,并調(diào)整元素的 transform: scale(0); 到 transform: scale(1);, 通過計算點(diǎn)擊的位置來設(shè)置 波紋元素 的大小和位置,以達(dá)到波紋擴(kuò)散的效果。

我將組件分為兩個部分, circleRipple.vue 和 TouchRipple.vue 各自實(shí)現(xiàn)不同的功能

  1. circleRipple.vue 波紋擴(kuò)散組件,完成波紋擴(kuò)散的效果
  2. TouchRipple.vue 監(jiān)聽 mouse 和 touch 相關(guān)事件,控制 circleRipple 的顯示,位置。

circleRipple.vue

circleRipple 需要完成波紋擴(kuò)展的效果,而且可以從外部控制它的大小和位置, 所以利用 vue 的 transition 動畫完成效果, 提供mergeStyle 、 color 、opacity 參數(shù)來從外部控制它的樣式。實(shí)現(xiàn)代碼如下。

 
 
  1.  
  2.  
  3.  
  4.  
  5.  
  6. @import "../styles/import.less"; 
  7. .mu-circle-ripple{ 
  8.   position: absolute; 
  9.   width: 100%; 
  10.   height: 100%; 
  11.   left: 0; 
  12.   top: 0; 
  13.   pointer-events: none; 
  14.   user-select: none; 
  15.   border-radius: 50%; 
  16.   background-color: currentColor; 
  17.   background-clip: padding-box; 
  18.   opacity: 0.1; 
  19.  
  20. .mu-ripple-enter-active, .mu-ripple-leave-active{ 
  21.   transition: transform 1s @easeOutFunction, opacity 2s @easeOutFunction; 
  22.  
  23. .mu-ripple-enter { 
  24.   transform: scale(0); 
  25.  
  26. .mu-ripple-leave-active{ 
  27.   opacity: 0 !important; 
  28.  

 vue2 對于動畫方面做了比較大的修改,除了把指令換成組件外,它還可以完成更復(fù)雜的動畫效果,具體可以看這里 vue2 transition

TouchRipple.vue

TouchRipple 需要控制 circleRipple 的顯示。完成以下內(nèi)容:

  1. 監(jiān)聽 mouse 和 touch 相關(guān)事件, 控制 circleRipple 的顯示。
  2. 通過點(diǎn)擊事件 event 對象, 計算出 circleRipple 的大小和位置
  3. 如果頻繁點(diǎn)擊可能出現(xiàn)多個 circleRipple

首先,基本模板 + 數(shù)據(jù)模型

 
 
  1.  
  2.  
  3.  

 開始和結(jié)束波紋效果

增加一個波紋元素只需要在 ripple 增加一個 object 即可,不同的是當(dāng)需要從點(diǎn)擊處擴(kuò)展時,需要計算一下波紋元素的大小和位置。

 
 
  1.   // isRippleTouchGenerated 是否是touch 事件開始的 
  2.   start (event, isRippleTouchGenerated) { 
  3.     // 過濾 touchstart 和 mousedown 同時存在的情況 
  4.     if (this.ignoreNextMouseDown && !isRippleTouchGenerated) { 
  5.       this.ignoreNextMouseDown = false 
  6.       return 
  7.     } 
  8.      
  9.     // 添加一個 波紋元素組件 
  10.     this.ripples.push({ 
  11.       key: this.nextKey++,  
  12.       color: this.color, 
  13.       opacity: this.opacity, 
  14.       style: this.centerRipple ? {} : this.getRippleStyle(event) // 不是從中心擴(kuò)展的需要計算波紋元素的位置 
  15.     }) 
  16.     this.ignoreNextMouseDown = isRippleTouchGenerated 
  17.  }, 
  18.  end () { 
  19.    if (this.ripples.length === 0) return 
  20.    this.ripples.splice(0, 1) // 刪除一個波紋元素 
  21.    this.stopListeningForScrollAbort() // 結(jié)束 touch 滾動的處理 
  22.   } 

 因?yàn)?vue2 基于 Virtual DOM 的, 所以如果沒有 key 在增加一個元素又同時刪除一個元素的時候,dom tree并沒有發(fā)生變化,是不會產(chǎn)生動畫效果的。

監(jiān)聽 mousedown 和 touchstart

mousedown 和 touchstart 處理上會有所不同,但都是用來啟動波紋效果的, touch涉及到多點(diǎn)點(diǎn)擊的問題,我們一般取***個即可。

 
 
  1.     handleMouseDown (event) { 
  2.       // 只監(jiān)聽鼠標(biāo)左鍵的點(diǎn)擊 
  3.       if (event.button === 0) { 
  4.         this.start(event, false) 
  5.       } 
  6.     }, 
  7.     handleTouchStart (event) { 
  8.       event.stopPropagation() // 防止多個波紋點(diǎn)擊組件嵌套 
  9.       if (event.touches) { 
  10.         this.startListeningForScrollAbort(event) // 啟動 touchmove 觸發(fā)滾動處理 
  11.         this.startTime = Date.now() 
  12.       } 
  13.       this.start(event.touches[0], true) 
  14.     } 

 touchmove控制

當(dāng)發(fā)生touchMove事件是需要判斷是否,移動的距離和時間,然后結(jié)束小波紋點(diǎn)擊小姑

 
 
  1.   // touchmove 結(jié)束波紋控制 
  2.   stopListeningForScrollAbort () { 
  3.     if (!this.handleMove) this.handleMove = this.handleTouchMove.bind(this) 
  4.     document.body.removeEventListener('touchmove', this.handleMove, false) 
  5.   }, 
  6.   startListeningForScrollAbort (event) { 
  7.     this.firstTouchY = event.touches[0].clientY 
  8.     this.firstTouchX = event.touches[0].clientX 
  9.     document.body.addEventListener('touchmove', this.handleMove, false) 
  10.   }, 
  11.   handleTouchMove (event) { 
  12.     const timeSinceStart = Math.abs(Date.now() - this.startTime) 
  13.     if (timeSinceStart > 300) { 
  14.       this.stopListeningForScrollAbort() 
  15.       return 
  16.     } 
  17.     const deltaY = Math.abs(event.touches[0].clientY - this.firstTouchY) 
  18.     const deltaX = Math.abs(event.touches[0].clientX - this.firstTouchX) 
  19.     // 滑動范圍在 > 6px 結(jié)束波紋點(diǎn)擊效果 
  20.     if (deltaY > 6 || deltaX > 6) this.end() 
  21.   } 

 計算波紋的位置和大小

需要從點(diǎn)擊處擴(kuò)散的波紋效果,需要計算波紋元素的大小和位置

 
 
  1.   getRippleStyle (event) { 
  2.     let holder = this.$refs.holder 
  3.     //  這個方法返回一個矩形對象,包含四個屬性:left、top、right和bottom。分別表示元素各邊與頁面上邊和左邊的距離。 
  4.     let rect = holder.getBoundingClientRect()  
  5.     // 獲取點(diǎn)擊點(diǎn)的位置 
  6.     let x = event.offsetX 
  7.     let y 
  8.     if (x !== undefined) { 
  9.       y = event.offsetY 
  10.     } else { 
  11.       x = event.clientX - rect.left 
  12.       y = event.clientY - rect.top 
  13.     } 
  14.     // 獲取***邊長 
  15.     let max 
  16.     if (rect.width === rect.height) { 
  17.       max = rect.width * 1.412 
  18.     } else { 
  19.       max = Math.sqrt( 
  20.         (rect.width * rect.width) + (rect.height * rect.height) 
  21.       ) 
  22.     } 
  23.     const dim = (max * 2) + 'px' 
  24.     return { 
  25.       width: dim, 
  26.       height: dim, 
  27.       // 通過margin控制波紋中心點(diǎn)和點(diǎn)擊點(diǎn)一致 
  28.       'margin-left': -max + x + 'px', 
  29.       'margin-top': -max + y + 'px' 
  30.     } 
  31.   } 

 使用

由于 touchRipple 內(nèi)部都是 position:absolute 布局,使用時,需要在外部加上 position:relative

 
 
  1. // listItem.vue 
  2.     @touchcancel="hover = false" class="mu-item-wrapper" :class="{'hover': hover}"> 
  3.      
  4.        
  5.          
  6.       
 
  •        
  •         // ... 
  •       
  •  
  •      
  •  
  •  
  •  ***

    到這點(diǎn)擊波紋組件就開發(fā)完了, 這些代碼借鑒了 keen-ui 和 material-ui 的實(shí)現(xiàn)方式。


    文章題目:如何使用vue開發(fā)波紋點(diǎn)擊特效組件
    文章URL:http://www.dlmjj.cn/article/djdpscg.html