Marquee.vue 1.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. <!--
  2. * @Author: LiZhiWei
  3. * @Date: 2026-01-14 16:44:03
  4. * @LastEditors: LiZhiWei
  5. * @LastEditTime: 2026-01-14 16:55:35
  6. * @Description:
  7. -->
  8. <template>
  9. <div
  10. class="group flex overflow-hidden py-24px [--duration:40s] [--gap:1rem] [gap:var(--gap)]"
  11. :class="vertical ? 'flex-col' : 'flex-row'"
  12. >
  13. <div
  14. v-for="i in 2"
  15. :key="i"
  16. class="flex shrink-0 [gap:var(--gap)]"
  17. :class="[
  18. vertical ? 'animate-marquee-vertical flex-col' : 'animate-marquee flex-row',
  19. pauseOnHover ? 'group-hover:[animation-play-state:paused]' : '',
  20. ]"
  21. :style="{
  22. animationDirection: reverse ? 'reverse' : 'normal',
  23. }"
  24. >
  25. <slot />
  26. </div>
  27. </div>
  28. </template>
  29. <script setup lang="ts">
  30. interface Props {
  31. vertical?: boolean
  32. reverse?: boolean
  33. pauseOnHover?: boolean
  34. }
  35. withDefaults(defineProps<Props>(), {
  36. vertical: false,
  37. reverse: false,
  38. pauseOnHover: false,
  39. })
  40. </script>
  41. <style scoped>
  42. .animate-marquee {
  43. animation: marquee var(--duration) linear infinite;
  44. animation-delay: var(--delay, 0s);
  45. }
  46. .animate-marquee-vertical {
  47. animation: marquee-vertical var(--duration) linear infinite;
  48. animation-delay: var(--delay, 0s);
  49. }
  50. @keyframes marquee {
  51. from {
  52. transform: translateX(0);
  53. }
  54. to {
  55. transform: translateX(calc(-100% - var(--gap)));
  56. }
  57. }
  58. @keyframes marquee-vertical {
  59. from {
  60. transform: translateY(0);
  61. }
  62. to {
  63. transform: translateY(calc(-100% - var(--gap)));
  64. }
  65. }
  66. </style>