css3 -- achieve click ripple effect

Keywords: Vue Mobile less

  1. Pure css for ripple effect
    Note: use pseudo element: after to define the ripple effect. At the beginning, opacity is 0, which is invisible to the user. Click and enter the active state. Opacity becomes 0.3, which is not zoomed. transition: 0s. After exiting the active state, it will display again naturally: after the style in the after mode, the opacity changes to 0, and the magnification is 10 times. Because the transition is set for 1s, there is a visible change process.
    The effect users see: a circle gradually becomes larger and lighter, and finally disappears.
    Disadvantages: using css to achieve, we can not locate the mouse position, and the position of each ripple is fixed.

    <button class="btn ripple">Button</button>
    
    .btn {
      position: relative;
      margin: 0 auto;
      width: 200px;
      height: 50px;
      line-height: 50px;
      border-radius: 4px;
      box-shadow: 0 0 10px gray;
      background-color: #fff;
      overflow: hidden;
      cursor: pointer;
    }
    
    .ripple {
        position: relative;
        //Hide overflow radial gradient background
        overflow: hidden;
    }
    
    .ripple:after {
        content: "";
        display: block;
        position: absolute;
        width: 100%;
        height: 100%;
        top: 0;
        left: 0;
        pointer-events: none;
        background-image: radial-gradient(circle, #666 10%, transparent 20%);
        background-repeat: no-repeat;
        background-position: 50%;
        transform: scale(10, 10);
        opacity: 0;
        transition: transform 1s, opacity 1s;
    }
    
    .ripple:active:after {
     //Set initial state
        transform: scale(0, 0);
        opacity: .3;
        transition: 0s;
    }
    
  2. Using js to achieve ripple effect
    Note: using js can get the mouse (finger) position, thus changing the ripple position. Here I use vue to encapsulate a component ==
    The monitored events are touch start and touch end (mobile phone). The computer can be changed to mousedown and mouseup (mouse event)

    <template>
      <div class="ripple--wapper" ref="rootElement">
        <div class="ripple--container" ref="rippleContainer" @touchstart="showRipple" @touchend="cleanRipple"></div>
        <slot />
      </div>
    </template>
    
    <script>
    export default {
      name:'ripple',
      data () {
        return {
          timer: 0
        }
      },
      props: {
        size: {
          type: Number,
          default: 100
        }
      },
      deactivated () {
        if(this.timer) {
          clearTimeout(this.timer)
        }
        while (this.$refs.rippleContainer.firstChild) {
          this.$refs.rippleContainer.removeChild(this.$refs.rippleContainer.firstChild)
        }
      },
      methods:{
        showRipple (e) {
          const target = this.$refs.rippleContainer
          const ripple = document.createElement('span')
          const size = this.size
          const pos = this.$refs.rippleContainer.getBoundingClientRect()
          const clientX = e.targetTouches[0].clientX
          const clientY = e.targetTouches[0].clientY
          const x = clientX - pos.left - size / 2
          const y = clientY - pos.top - size / 2
          const style = `top:${y/50}rem;left:${x/50}rem;width:${size/50}rem;height:${size/50}rem`
          ripple.setAttribute('style', style)
          const container = this.$refs.rippleContainer
          container.appendChild(ripple)
        },
        cleanRipple () {
          const _this = this
          if(this.timer) {
            clearTimeout(this.timer)
          }
          this.timer=setTimeout(() =>{
            //Clear ripple
            if (_this.$refs.rippleContainer && _this.$refs.rippleContainer.firstChild) {
              _this.$refs.rippleContainer.removeChild(_this.$refs.rippleContainer.firstChild)
            }
          }, 1000)
        }
      }
    }
    </script>
    <style lang="less">
    @import "~assets/variable";
    .ripple--wapper {
      position: relative;
      overflow: hidden;
      //Disable text selection
      -webkit-user-select: none;
      -moz-user-select: none;
      -webkit-user-select:none;  
      -o-user-select:none;  
      user-select:none;
      .ripple--container {
        position: absolute;
        top: 0;
        right: 0;
        bottom: 0;
        left: 0;
        span {
          position: absolute;
          transform: scale(0);
          border-radius: 100%;
          opacity: .3;
          background-color: #333;
          animation: ripple .2s;
        }
        @keyframes ripple {
          to {
            opacity: 0;
            transform: scale(2);
          }
        }
      }
    }
    </style>
    

Posted by lpxxfaintxx on Sat, 21 Dec 2019 07:33:13 -0800