MilestoneCelebration.vue 2.1 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192
  1. <template>
  2. <view class="celebration-overlay" v-if="visible" @click="dismiss" @touchmove.stop.prevent>
  3. <!-- CSS粒子 -->
  4. <view
  5. class="celebration-particle"
  6. v-for="p in particles"
  7. :key="p.id"
  8. :style="{
  9. left: p.left + '%',
  10. animationDelay: p.delay + 's',
  11. animationDuration: p.duration + 's',
  12. background: p.color,
  13. width: p.size + 'rpx',
  14. height: p.size + 'rpx'
  15. }">
  16. </view>
  17. <!-- 文字 -->
  18. <view class="celebration-content">
  19. <text class="celebration-title">{{ title }}</text>
  20. <text class="celebration-subtitle">{{ subtitle }}</text>
  21. </view>
  22. </view>
  23. </template>
  24. <script>
  25. export default {
  26. props: {
  27. visible: { type: Boolean, default: false },
  28. title: { type: String, default: '' },
  29. subtitle: { type: String, default: '' },
  30. particles: { type: Array, default: function() { return [] } }
  31. },
  32. methods: {
  33. dismiss: function() {
  34. this.$emit('dismiss')
  35. }
  36. }
  37. }
  38. </script>
  39. <style scoped>
  40. .celebration-overlay {
  41. position: fixed;
  42. top: 0;
  43. left: 0;
  44. right: 0;
  45. bottom: 0;
  46. z-index: 9998;
  47. background: rgba(0,0,0,0.6);
  48. display: flex;
  49. align-items: center;
  50. justify-content: center;
  51. overflow: hidden;
  52. }
  53. .celebration-particle {
  54. position: absolute;
  55. top: -20rpx;
  56. border-radius: 50%;
  57. animation: particleFall linear forwards;
  58. opacity: 0.9;
  59. }
  60. .celebration-content {
  61. display: flex;
  62. flex-direction: column;
  63. align-items: center;
  64. gap: 16rpx;
  65. z-index: 1;
  66. animation: celebrationTextIn 0.5s cubic-bezier(0.175, 0.885, 0.32, 1.275) forwards;
  67. }
  68. .celebration-title {
  69. font-size: 56rpx;
  70. font-weight: 800;
  71. color: #fff;
  72. text-shadow: 0 4rpx 20rpx rgba(0,0,0,0.3);
  73. }
  74. .celebration-subtitle {
  75. font-size: 32rpx;
  76. color: rgba(255,255,255,0.9);
  77. }
  78. </style>
  79. <style>
  80. @keyframes particleFall {
  81. 0% { transform: translateY(-20rpx) rotate(0deg); opacity: 0.9; }
  82. 50% { opacity: 1; }
  83. 100% { transform: translateY(110vh) rotate(720deg); opacity: 0; }
  84. }
  85. @keyframes celebrationTextIn {
  86. 0% { transform: scale(0) rotate(-10deg); opacity: 0; }
  87. 100% { transform: scale(1) rotate(0deg); opacity: 1; }
  88. }
  89. </style>