主要通过更换 css 上的 animation 来实现涟漪效果。

但是大部分的实现方法会增加一个空白节点,

所以想出通过操作伪元素的方案来做。

代码如下

在线体验

  1. <!DOCTYPE html>
  2. <html lang="en">
  3. <head>
  4. <meta charset="UTF-8" />
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  6. <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  7. <title>Document</title>
  8. <style>
  9. .input {
  10. padding: 5em 10em;
  11. border-radius: 0.3em;
  12. position: relative;
  13. background-color: rgb(189, 86, 86);
  14. display: inline-block;
  15. overflow: hidden;
  16. }
  17. .input1::after {
  18. content: "";
  19. display: block;
  20. width: 6px;
  21. height: 6px;
  22. border-radius: 50%;
  23. position: absolute;
  24. /* transition: all 0.4s ease-in-out; */
  25. z-index: 1111;
  26. transform: scale(0);
  27. /* top: 0;
  28. left: 0; */
  29. /* animation: spin 01s linear; */
  30. background-color: rgba(0, 0, 0, 0.45);
  31. }
  32. @keyframes spin {
  33. 0% {
  34. transform: scale(0);
  35. background-color: rgba(0, 0, 0, 0.45);
  36. }
  37. 100% {
  38. transform: scale(150);
  39. background-color: transparent;
  40. }
  41. }
  42. </style>
  43. </head>
  44. <body>
  45. <div onclick="fn(event)" class="input input1">
  46. 这是一个按钮
  47. </div>
  48. <script>
  49. // 这是一个操作伪元素样式的方法
  50. function ruleSelector(selector) {
  51. function uni(selector) {
  52. return selector.replace(/::/g, ":");
  53. }
  54. // es6
  55. return Array.from(document.styleSheets)
  56. .reduce((a, b) => {
  57. return a.concat(Array.from(b.cssRules));
  58. }, [])
  59. .filter(x => {
  60. return x.selectorText === selector;
  61. });
  62. // es5
  63. // return Array.prototype.filter.call(Array.prototype.concat.apply([], Array.prototype.map.call(document.styleSheets, function (x) {
  64. // return Array.prototype.slice.call(x.cssRules);
  65. // })), function (x) {
  66. // return uni(x.selectorText) === uni(selector);
  67. // });
  68. }
  69. function fn(e) {
  70. ruleSelector(".input1::after")[0].style.top = e.offsetY - parseInt(ruleSelector(".input1::after")[0].style.width,
  71. 10) / 2 + "px";
  72. ruleSelector(".input1::after")[0].style.left = e.offsetX - parseInt(ruleSelector(".input1::after")[0].style
  73. .height, 10) / 2 + "px";
  74. ruleSelector(".input1::after")[0].style.animation = '';
  75. setTimeout(() => { // 不这样做会被合并
  76. ruleSelector(".input1::after")[0].style.animation = 'spin .5s linear';
  77. })
  78. }
  79. </script>
  80. </body>
  81. </html>