Results show

Thinking points

  1. Vue V-for dynamically updates waves to generate water ripple data by inserting water ripple data into the waves push operation of the array
  2. The water ripple uses fixed positioning to map the top and left attributes of the DOM of the water ripple by clicking the clientX and clientY attributes of the event
  3. Scale amplification is used as the diffusion effect for water ripples, which increases exponentially from inside to outside to simulate the effect of bigger and bigger ripples. The effect of attenuation is realized using opacity property
  4. Define initial state of each circle of water ripple, and overall transition to scale(1), opacity: 0; And maintain this final state;
  5. As the number of clicks increases, the DOM grows, periodically checking for clicks and empties the waves array if there are none
  6. Random generation of ripple size data, rich ripple effect

use

Just reference it in app.vue

The following code

//waves.vue
<template>
  <div data-tname="WaveItem">
    <div class="main-container">
      <div class="waves">
        <div class="wave" v-for="(item, key) in waves" :key="key" :style="item">
          <div
            v-for="n in wavesConfig.total"
            :key="n"
            class="wave-item"
            :style="{transform: 'scale(${0.1 * math.sqrt (n-1)})', // makes the ripple size increase index: 0.3 * (1 / n), // Because the opacity of the overlapping ripples will be superimposed on each other, the smaller the ripples need to be the lower opacity, so as not to overload the center color. AnimationDuration: ${(n-1) * 0.12}s', // The larger the ripple, the later the ripple, to show the effect of gradually spread animationDuration: ${0.6 + n * 0.3 + parseInt(item.width) * 0.002}s', // The animation time of the ripple is gradually increased, showing the effect of the ripple spreading out slowly, the larger the ripple size, the longer the animation time. backgroundColor: wavesConfig.waveColor }"
          ></div>
        </div>
      </div>
    </div>
  </div>
</template>

<script>
export default {
  name: "WaveItem".data() {
    return {
      waves: [].wavesConfig: {
        maxSize: 300.// the maximum size of the ripple
        minSize: 100.// px, minimum size of ripple
        zIndexCount: 999.// The z-index value of the wavy parent element
        waveColor: "#3E8CE3".// Wave base color
        total: 5 // The number of circles
      },
      clear: {
        delay: 5000.timeoutId: null}}; },mounted() {
    document.getElementById("app").onclick = e= > {
      this.createWave(e);
      this.intervalClearWave();
    };
  },
  methods: {
    createWave(e) {
      // Make the newly generated ripple always overlay on top of the previous ripple
      if (this.wavesConfig.zIndexCount > 99999) {
        this.wavesConfig.zIndexCount = 999;
      } else {
        this.wavesConfig.zIndexCount++;
      }
      // Generate a random ripple size within a certain range
      const waveSize = parseInt(
        Math.random() * (this.wavesConfig.maxSize - this.wavesConfig.minSize) +
          this.wavesConfig.minSize
      );
      // Add new ripple data
      this.waves.push({
        left: `${e.clientX - waveSize / 2}px`.top: `${e.clientY - waveSize / 2}px`.zIndex: this.wavesConfig.zIndexCount,
        width: `${waveSize}px`.height: `${waveSize}px`
      });
    },
    intervalClearWave() {
      clearTimeout(this.clear.timeoutId);
      this.clear.timeoutId = setTimeout(() = > {
        this.waves = [];
      }, this.clear.delay); }}};</script>

<style lang="scss" scoped>
.waves {
  .wave {
    position: fixed;
    pointer-events: none; // Click event penetration, so that mouse click can penetrate ripples, compatible with IE11 and above@keyframes wave {
      to{// The ripple becomes larger and more transparenttransform: scale(1);
        opacity: 0; }}.wave-item {
      width: 100%;
      height: 100%;
      position: absolute;
      border-radius: 100%;
      animation: { name: wave; fill-mode: forwards; // Keep the state of the last frame after the animation ends. Timing -function: ease-out; // Ripples spread out gradually}}}}</style>


Copy the code