水波纹效果,多功能-vue组件

2022-02-03  本文已影响0人  littlesunn
1643746641656202222437161.gif
<template>
  <div class="water-ripples-container" ref="water-ripples-container" @[trigger]="onActive">
    <div ref="ripples" :class="{'out-ripples': isOut, 'inset-ripples': type == 'inset', 
    'animate-always--out': isActive && trigger == 'always' && type == 'out',
    'animate-once--out': isActive && (trigger == 'mouseenter' || trigger == 'click') && type == 'out',
    'animate-always--inset': isActive && trigger == 'always' && type == 'inset',
    'animate-once--inset': isActive && (trigger == 'mouseenter' || trigger == 'click') && type == 'inset',
    }" :style="{
        borderRadius:  isOut ? borderRadius : '50%',
        '--ripple-color': color,
        '--spread-width': spreadWidth,
        '--spread-size': mySpreadSize,
    }"></div>
    <slot />
  </div>
</template>

<script>
export default {
  props: {
    type: {
      type: String,
      default: "out"  // out/inset
    },
    color: {
      type: String,
      default: "#337ab7"
    },
    borderRadius: {
      type: String,
      default: "0"
    },
    spreadWidth: {
      type: String,
      default: "8px"
    },
    trigger: {
      type: String,
      default: "always"  // always/mouseenter/click/focus
    },
    spreadSize: {
      type: String,
      default: null
    }
  },
  data() {
    return {
      isActive: false,
      mySpreadSize: '0px'
    }
  },
  computed: {
    isOut() {
      return this.type == "out"
    }
  },
  mounted() {
    this.initWidth();

  },
  watch: {
    trigger: {
      handler(val) {
        this.isActive = (val == "always")
      },
      immediate: true
    }
  },
  methods: {
    onActive() {
      this.isActive = true
    },
    initWidth() {
      let container = this.$refs['water-ripples-container']
      let ripples = this.$refs['ripples']
      if (this.type == "out") {
        this.$refs['ripples'].style.width = container.clientWidth + "px";
      } else {
        container.style.overflow = "hidden";
        if (!this.spreadSize) {
          this.mySpreadSize = container.clientWidth * 1.1 + "px"
        }else {
          this.mySpreadSize = this.spreadSize
        }
        console.log(this.spreadSize, "this.spreadSize");
      }
      ripples.addEventListener('animationend', () => {
        this.isActive = false
      }, false);
    }
  }
}
</script>

<style scoped lang="scss">
.water-ripples-container {
  position: relative;
  display: inline-block;
  .slot-container {
    position: relative;
    z-index: 2;
  }
  .out-ripples {
    position: absolute;
    left: 0;
    top: 0;
    height: 100%;
    opacity: 1;
    z-index: 1;
    pointer-events: none;
  }
  .animate-once--out {
    animation: ripple-effect 1s forwards;
  }
  .animate-always--out {
    animation: ripple-effect 1s infinite;
  }
  @keyframes ripple-effect {
    0% {
      box-shadow: 0 0 0 0px var(--ripple-color);
      opacity: 1;
    }
    100% {
      box-shadow: 0 0 0 var(--spread-width) var(--ripple-color);
      opacity: 0;
    }
  }

  .inset-ripples {
    position: absolute;
    left: 50%;
    top: 50%;
    transform: translate(-50%, -50%);
    opacity: 1;
    width: 0px;
    height: 0px;
    background: red;
    pointer-events: none;
  }
  @keyframes size-effect {
    0% {
      width: 0px;
      height: 0px;
      opacity: 0.8;
    }
    100% {
      width: var(--spread-size);
      height: var(--spread-size);
      opacity: 0;
    }
  }
  .animate-once--inset {
    animation: size-effect 1s forwards;
  }
  .animate-always--inset {
    animation: size-effect 1s infinite;
  }
}
</style>
上一篇下一篇

猜你喜欢

热点阅读