index.vue 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109
  1. //waves.vue
  2. <template>
  3. <div data-tname="WaveItem">
  4. <div class="main-container">
  5. <div class="waves">
  6. <div class="wave" v-for="(item, key) in waves" :key="key" :style="item">
  7. <div
  8. v-for="n in wavesConfig.total"
  9. :key="n"
  10. class="wave-item"
  11. :style="{
  12. transform: `scale(${0.1 * Math.sqrt(n - 1)})`, // 使得波纹大小指数增长
  13. opacity: 0.3 * (1 / n), // 因为相互层叠的波纹透明度会相互叠加,需要越小的波纹透明度越低,以免中心颜色过重
  14. animationDelay: `${(n - 1) * 0.12}s`, // 越大的波纹越晚出现,以呈现波纹逐渐扩散的效果
  15. animationDuration: `${
  16. 0.6 + n * 0.3 + parseInt(item.width) * 0.002
  17. }s`, // 波纹动画时间渐增,表现波纹向外扩散渐慢的效果,波纹尺寸越大动画时间越长。
  18. backgroundColor: wavesConfig.waveColor,
  19. }"
  20. ></div>
  21. </div>
  22. </div>
  23. </div>
  24. </div>
  25. </template>
  26. <script>
  27. export default {
  28. name: "WaveItem",
  29. data() {
  30. return {
  31. waves: [],
  32. wavesConfig: {
  33. maxSize: 80, // px,波纹最大尺寸
  34. minSize: 30, // px,波纹最小尺寸
  35. zIndexCount: 9999, // 波纹父元素其z-index数值
  36. waveColor: "#3E8CE3", //波纹基础颜色
  37. total: 5, //波纹圈层数
  38. },
  39. clear: {
  40. delay: 5000,
  41. timeoutId: null,
  42. },
  43. };
  44. },
  45. mounted() {
  46. document.getElementById("app").onclick = (e) => {
  47. this.createWave(e);
  48. this.intervalClearWave();
  49. };
  50. },
  51. methods: {
  52. createWave(e) {
  53. // 让新生成的波纹始终在之前波纹的上层产生叠加效果
  54. if (this.wavesConfig.zIndexCount > 999999999) {
  55. this.wavesConfig.zIndexCount = 999999999;
  56. } else {
  57. this.wavesConfig.zIndexCount++;
  58. }
  59. // 在一定范围内随机生成波纹的大小
  60. const waveSize = parseInt(
  61. Math.random() * (this.wavesConfig.maxSize - this.wavesConfig.minSize) +
  62. this.wavesConfig.minSize
  63. );
  64. //添加新的波纹数据
  65. this.waves.push({
  66. left: `${e.clientX - waveSize / 2}px`,
  67. top: `${e.clientY - waveSize / 2}px`,
  68. zIndex: this.wavesConfig.zIndexCount,
  69. width: `${waveSize}px`,
  70. height: `${waveSize}px`,
  71. });
  72. },
  73. intervalClearWave() {
  74. clearTimeout(this.clear.timeoutId);
  75. this.clear.timeoutId = setTimeout(() => {
  76. this.waves = [];
  77. }, this.clear.delay);
  78. },
  79. },
  80. };
  81. </script>
  82. <style lang="scss" scoped>
  83. .waves {
  84. .wave {
  85. position: fixed;
  86. pointer-events: none; // 点击事件穿透,使得鼠标点击可以穿透波纹,兼容ie11及以上
  87. @keyframes wave {
  88. to {
  89. //波纹逐渐扩散变大变透明
  90. transform: scale(1);
  91. opacity: 0;
  92. }
  93. }
  94. .wave-item {
  95. width: 100%;
  96. height: 100%;
  97. position: absolute;
  98. border-radius: 100%;
  99. animation: {
  100. name: wave;
  101. fill-mode: forwards; // 动画结束后保持最后一帧的状态
  102. timing-function: ease-out; // 波纹向外扩散渐缓
  103. }
  104. }
  105. }
  106. }
  107. </style>