如何使用vue开发波纹点击特效组件

最近在使用 vue2 做一个新的 material ui 库,波纹点击效果在 material design 中被多次使用到,于是决定把它封装成一个公共的组件,使用时直接调用就好啦。

开发之前的思考

常见的波纹点击效果的实现方式是监听元素的 mousedown 事件,在元素内部创建一个 波纹元素 ,并调整元素的 transform: scale(0); 到 transform: scale(1);, 通过计算点击的位置来设置 波纹元素 的大小和位置,以达到波纹扩散的效果。

我将组件分为两个部分, circleRipple.vue 和 TouchRipple.vue 各自实现不同的功能

  1. circleRipple.vue 波纹扩散组件,完成波纹扩散的效果
  2. TouchRipple.vue 监听 mouse 和 touch 相关事件,控制 circleRipple 的显示,位置。

circleRipple.vue

circleRipple 需要完成波纹扩展的效果,而且可以从外部控制它的大小和位置, 所以利用 vue 的 transition 动画完成效果, 提供mergeStyle 、 color 、opacity 参数来从外部控制它的样式。实现代码如下。

 
 
  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 对于动画方面做了比较大的修改,除了把指令换成组件外,它还可以完成更复杂的动画效果,具体可以看这里 vue2 transition

TouchRipple.vue

TouchRipple 需要控制 circleRipple 的显示。完成以下内容:

  1. 监听 mouse 和 touch 相关事件, 控制 circleRipple 的显示。
  2. 通过点击事件 event 对象, 计算出 circleRipple 的大小和位置
  3. 如果频繁点击可能出现多个 circleRipple

首先,基本模板 + 数据模型

 
 
  1.  
  2.  
  3.  

 开始和结束波纹效果

增加一个波纹元素只需要在 ripple 增加一个 object 即可,不同的是当需要从点击处扩展时,需要计算一下波纹元素的大小和位置。

 
 
  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) // 不是从中心扩展的需要计算波纹元素的位置 
  15.     }) 
  16.     this.ignoreNextMouseDown = isRippleTouchGenerated 
  17.  }, 
  18.  end () { 
  19.    if (this.ripples.length === 0) return 
  20.    this.ripples.splice(0, 1) // 删除一个波纹元素 
  21.    this.stopListeningForScrollAbort() // 结束 touch 滚动的处理 
  22.   } 

 因为 vue2 基于 Virtual DOM 的, 所以如果没有 key 在增加一个元素又同时删除一个元素的时候,dom tree并没有发生变化,是不会产生动画效果的。

监听 mousedown 和 touchstart

mousedown 和 touchstart 处理上会有所不同,但都是用来启动波纹效果的, touch涉及到多点点击的问题,我们一般取***个即可。

 
 
  1.     handleMouseDown (event) { 
  2.       // 只监听鼠标左键的点击 
  3.       if (event.button === 0) { 
  4.         this.start(event, false) 
  5.       } 
  6.     }, 
  7.     handleTouchStart (event) { 
  8.       event.stopPropagation() // 防止多个波纹点击组件嵌套 
  9.       if (event.touches) { 
  10.         this.startListeningForScrollAbort(event) // 启动 touchmove 触发滚动处理 
  11.         this.startTime = Date.now() 
  12.       } 
  13.       this.start(event.touches[0], true) 
  14.     } 

 touchmove控制

当发生touchMove事件是需要判断是否,移动的距离和时间,然后结束小波纹点击小姑

 
 
  1.   // touchmove 结束波纹控制 
  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 结束波纹点击效果 
  20.     if (deltaY > 6 || deltaX > 6) this.end() 
  21.   } 

 计算波纹的位置和大小

需要从点击处扩散的波纹效果,需要计算波纹元素的大小和位置

 
 
  1.   getRippleStyle (event) { 
  2.     let holder = this.$refs.holder 
  3.     //  这个方法返回一个矩形对象,包含四个属性:left、top、right和bottom。分别表示元素各边与页面上边和左边的距离。 
  4.     let rect = holder.getBoundingClientRect()  
  5.     // 获取点击点的位置 
  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控制波纹中心点和点击点一致 
  28.       'margin-left': -max + x + 'px', 
  29.       'margin-top': -max + y + 'px' 
  30.     } 
  31.   } 

 使用

由于 touchRipple 内部都是 position:absolute 布局,使用时,需要在外部加上 position:relative

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

    到这点击波纹组件就开发完了, 这些代码借鉴了 keen-ui 和 material-ui 的实现方式。

    本文名称:如何使用vue开发波纹点击特效组件
    地址分享:http://www.shufengxianlan.com/qtweb/news23/368423.html

    网站建设、网络推广公司-创新互联,是专注品牌与效果的网站制作,网络营销seo公司;服务项目有等

    广告

    声明:本网站发布的内容(图片、视频和文字)以用户投稿、用户转载内容为主,如果涉及侵权请尽快告知,我们将会在第一时间删除。文章观点不代表本网站立场,如需处理请联系客服。电话:028-86922220;邮箱:631063699@qq.com。内容未经允许不得转载,或转载时需注明来源: 创新互联

    猜你还喜欢下面的内容

    电子商务知识

    行业网站建设