index.vue 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283
  1. <template>
  2. <div
  3. class="avatar-wrap"
  4. :style="{ '--width': size + 'px' }"
  5. >
  6. <div class="cycle-wrap">
  7. <div
  8. class="avatar"
  9. :style="{ backgroundImage: `url(${avatar})` }"
  10. ></div>
  11. <template v-if="living">
  12. <div class="cycle cycle-1"></div>
  13. <div class="cycle cycle-2"></div>
  14. <div class="cycle cycle-3"></div
  15. ></template>
  16. </div>
  17. <div class="border"></div>
  18. </div>
  19. </template>
  20. <script lang="ts" setup>
  21. withDefaults(
  22. defineProps<{
  23. avatar: string;
  24. size: number;
  25. living: boolean;
  26. }>(),
  27. {
  28. avatar: '',
  29. size: 100,
  30. living: false,
  31. }
  32. );
  33. </script>
  34. <style lang="scss" scoped>
  35. .avatar-wrap {
  36. position: relative;
  37. @keyframes scaleCycle {
  38. 0% {
  39. opacity: 1;
  40. transform: scale(1);
  41. }
  42. 100% {
  43. opacity: 0;
  44. transform: scale(1.5);
  45. }
  46. }
  47. .cycle-wrap {
  48. position: relative;
  49. width: var(--width);
  50. height: var(--width);
  51. .avatar {
  52. display: inline-block;
  53. margin: 0 auto;
  54. width: var(--width);
  55. height: var(--width);
  56. border-radius: 50%;
  57. @extend %containBg;
  58. }
  59. .cycle {
  60. position: absolute;
  61. top: 0;
  62. left: 0;
  63. width: var(--width);
  64. height: var(--width);
  65. border: 1px solid $theme-color-gold;
  66. border-radius: 50%;
  67. animation: scaleCycle 1.5s linear infinite;
  68. &.cycle-1 {
  69. animation-delay: 0;
  70. }
  71. &.cycle-2 {
  72. animation-delay: 0.5s;
  73. }
  74. &.cycle-3 {
  75. animation-delay: 1s;
  76. }
  77. }
  78. }
  79. }
  80. </style>