成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

vue 開發(fā)波紋點擊特效組件

chavesgu / 2925人閱讀

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

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

開發(fā)之前的思考

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

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

circleRipple.vue 波紋擴散組件,完成波紋擴散的效果

TouchRipple.vue 監(jiān)聽 mousetouch 相關(guān)事件,控制 circleRipple 的顯示,位置。

circleRipple.vue

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





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

TouchRipple.vue

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

監(jiān)聽 mousetouch 相關(guān)事件, 控制 circleRipple 的顯示。

通過點擊事件 event 對象, 計算出 circleRipple 的大小和位置

如果頻繁點擊可能出現(xiàn)多個 circleRipple

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



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

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

{
  // isRippleTouchGenerated 是否是touch 事件開始的
  start (event, isRippleTouchGenerated) {
    // 過濾 touchstart 和 mousedown 同時存在的情況
    if (this.ignoreNextMouseDown && !isRippleTouchGenerated) {
      this.ignoreNextMouseDown = false
      return
    }
    
    // 添加一個 波紋元素組件
    this.ripples.push({
      key: this.nextKey++, 
      color: this.color,
      opacity: this.opacity,
      style: this.centerRipple ? {} : this.getRippleStyle(event) // 不是從中心擴展的需要計算波紋元素的位置
    })
    this.ignoreNextMouseDown = isRippleTouchGenerated
 },
 end () {
   if (this.ripples.length === 0) return
   this.ripples.splice(0, 1) // 刪除一個波紋元素
   this.stopListeningForScrollAbort() // 結(jié)束 touch 滾動的處理
  }
}

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

監(jiān)聽 mousedown 和 touchstart

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

{
    handleMouseDown (event) {
      // 只監(jiān)聽鼠標(biāo)左鍵的點擊
      if (event.button === 0) {
        this.start(event, false)
      }
    },
    handleTouchStart (event) {
      event.stopPropagation() // 防止多個波紋點擊組件嵌套
      if (event.touches) {
        this.startListeningForScrollAbort(event) // 啟動 touchmove 觸發(fā)滾動處理
        this.startTime = Date.now()
      }
      this.start(event.touches[0], true)
    }
}
touchmove控制

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

{
  // touchmove 結(jié)束波紋控制
  stopListeningForScrollAbort () {
    if (!this.handleMove) this.handleMove = this.handleTouchMove.bind(this)
    document.body.removeEventListener("touchmove", this.handleMove, false)
  },
  startListeningForScrollAbort (event) {
    this.firstTouchY = event.touches[0].clientY
    this.firstTouchX = event.touches[0].clientX
    document.body.addEventListener("touchmove", this.handleMove, false)
  },
  handleTouchMove (event) {
    const timeSinceStart = Math.abs(Date.now() - this.startTime)
    if (timeSinceStart > 300) {
      this.stopListeningForScrollAbort()
      return
    }
    const deltaY = Math.abs(event.touches[0].clientY - this.firstTouchY)
    const deltaX = Math.abs(event.touches[0].clientX - this.firstTouchX)
    // 滑動范圍在 > 6px 結(jié)束波紋點擊效果
    if (deltaY > 6 || deltaX > 6) this.end()
  }
}
計算波紋的位置和大小

需要從點擊處擴散的波紋效果,需要計算波紋元素的大小和位置

{
  getRippleStyle (event) {
    let holder = this.$refs.holder
    //  這個方法返回一個矩形對象,包含四個屬性:left、top、right和bottom。分別表示元素各邊與頁面上邊和左邊的距離。
    let rect = holder.getBoundingClientRect() 
    // 獲取點擊點的位置
    let x = event.offsetX
    let y
    if (x !== undefined) {
      y = event.offsetY
    } else {
      x = event.clientX - rect.left
      y = event.clientY - rect.top
    }
    // 獲取最大邊長
    let max
    if (rect.width === rect.height) {
      max = rect.width * 1.412
    } else {
      max = Math.sqrt(
        (rect.width * rect.width) + (rect.height * rect.height)
      )
    }
    const dim = (max * 2) + "px"
    return {
      width: dim,
      height: dim,
      // 通過margin控制波紋中心點和點擊點一致
      "margin-left": -max + x + "px",
      "margin-top": -max + y + "px"
    }
  }
}
使用

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

// listItem.vue

    
      
// ...
最后

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

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/80395.html

相關(guān)文章

  • 構(gòu)建Vue.js組件:slider

    摘要:組件的使用場景很多,主要為圖片的展示。一個主要由頂層容器和每一幀的組成。更多關(guān)于由于支持多個可用戶自定義的,所以需要在中聲明這些支持的自定義屬性,以便在組件聲明時使用上一幀下一幀導(dǎo)航自動播放播放效果導(dǎo)航位置滑動特效組件支持兩種特效和。 Slider組件的使用場景很多,主要為圖片的展示。一個slider主要由頂層容器和每一幀的slide組成。下面通過一個例子嘗試基于Vue.js去構(gòu)建一個...

    zxhaaa 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<