当前位置: 首页 > news >正文

vue3 随机生产音符扩散效果

  1 <template>
  2   <div class="container">
  3     <div class="flower-center"></div>
  4     <div 
  5       class="note-petal"
  6       v-for="note in activeNotes"
  7       :key="note.id"
  8       :style="note.style"
  9     >
 10       {{ note.symbol }}
 11     </div>
 12     <div class="controls">
 13       <button @click="toggleAnimation">{{ isPlaying ? '暂停动画' : '播放动画' }}</button>
 14     </div>
 15   </div>
 16 </template>
 17 
 18 <script setup>
 19 import { ref, onMounted, onUnmounted } from 'vue'
 20 
 21 const activeNotes = ref([])
 22 const isPlaying = ref(true)
 23 let animationInterval = null
 24 let noteCounter = 0
 25 
 26 const noteSymbols = ['', '', '', '', '', '', '']
 27 const colors = [
 28   '#ff6b6b', '#4ecdc4', '#ffbe76', 
 29   '#a5d8ff', '#d8b4fe', '#ff9e9e', '#b5ead7'
 30 ]
 31 
 32 function createPetalGroup() {
 33   const newNotes = []
 34   // 随机生成5-12个音符
 35   const noteCount = Math.floor(Math.random() * 8) + 5
 36   
 37   for (let i = 0; i < noteCount; i++) {
 38     const angle = (i * (Math.PI * 2 / noteCount)) + (Math.random() * 0.5 - 0.25)
 39     const distance = 300 + Math.random() * 150
 40     const endX = Math.cos(angle) * distance
 41     const endY = Math.sin(angle) * distance
 42     const rotation = (Math.random() * 60 - 30)
 43     
 44     const noteId = `note-${Date.now()}-${noteCounter++}`
 45     
 46     newNotes.push({
 47       id: noteId,
 48       symbol: noteSymbols[Math.floor(Math.random() * noteSymbols.length)],
 49       style: {
 50         color: colors[Math.floor(Math.random() * colors.length)],
 51         '--end-x': `${endX}px`,
 52         '--end-y': `${endY}px`,
 53         '--rotation': `${rotation}deg`,
 54         'animation-duration': `${3 + Math.random() * 1.5}s`
 55       }
 56     })
 57   }
 58   
 59   activeNotes.value = [...activeNotes.value, ...newNotes]
 60   
 61   setTimeout(() => {
 62     activeNotes.value = activeNotes.value.filter(note => !newNotes.some(newNote => newNote.id === note.id))
 63   }, 4000)
 64 }
 65 
 66 function startAnimation() {
 67   if (animationInterval) clearInterval(animationInterval)
 68   createPetalGroup()
 69   animationInterval = setInterval(createPetalGroup, 1200)
 70   isPlaying.value = true
 71 }
 72 
 73 function stopAnimation() {
 74   clearInterval(animationInterval)
 75   isPlaying.value = false
 76 }
 77 
 78 function toggleAnimation() {
 79   if (isPlaying.value) {
 80     stopAnimation()
 81   } else {
 82     startAnimation()
 83   }
 84 }
 85 
 86 onMounted(() => {
 87   startAnimation()
 88 })
 89 
 90 onUnmounted(() => {
 91   stopAnimation()
 92 })
 93 </script>
 94 
 95 <style>
 96 .container {
 97   position: relative;
 98   width: 100vw;
 99   height: 100vh;
100   background: radial-gradient(circle at center, #1a2a6c, #2a5298);
101   overflow: hidden;
102 }
103 
104 .flower-center {
105   position: absolute;
106   width: 120px;
107   height: 120px;
108   top: 50%;
109   left: 50%;
110   transform: translate(-50%, -50%);
111   background: radial-gradient(circle, rgba(255,255,255,0.9) 0%, rgba(255,255,255,0) 80%);
112   border-radius: 50%;
113   z-index: 1;
114   animation: flowerPulse 3s ease-in-out infinite;
115 }
116 
117 @keyframes flowerPulse {
118   0%, 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.8; }
119   50% { transform: translate(-50%, -50%) scale(1.4); opacity: 1; }
120 }
121 
122 .note-petal {
123   position: absolute;
124   font-size: 48px;
125   top: 50%;
126   left: 50%;
127   transform: translate(-50%, -50%);
128   animation: petalBloom 4s ease-out forwards;
129   opacity: 0;
130   text-shadow: 0 0 20px currentColor;
131   z-index: 10;
132   will-change: transform, opacity;
133 }
134 
135 @keyframes petalBloom {
136   0% {
137     transform: translate(-50%, -50%) scale(0.5) rotate(0deg);
138     opacity: 0;
139     filter: blur(3px);
140   }
141   20% {
142     opacity: 1;
143     transform: translate(-50%, -50%) scale(1) rotate(0deg);
144     filter: blur(0);
145   }
146   80% {
147     opacity: 0.7;
148   }
149   100% {
150     transform: translate(var(--end-x), var(--end-y)) scale(0.3) rotate(var(--rotation));
151     opacity: 0;
152     filter: blur(2px);
153   }
154 }
155 
156 .controls {
157   position: absolute;
158   bottom: 40px;
159   left: 50%;
160   transform: translateX(-50%);
161   z-index: 100;
162 }
163 
164 button {
165   padding: 12px 24px;
166   background: linear-gradient(45deg, #ff6b6b, #ff8e8e);
167   border: none;
168   border-radius: 30px;
169   color: white;
170   font-weight: bold;
171   cursor: pointer;
172   transition: all 0.3s;
173   box-shadow: 0 4px 15px rgba(255, 107, 107, 0.4);
174 }
175 
176 button:hover {
177   transform: translateY(-3px);
178   box-shadow: 0 6px 20px rgba(255, 107, 107, 0.6);
179 }
180 </style>

 

http://www.rkmt.cn/news/57049.html

相关文章:

  • ASM1042A3S车规级CANFD芯片在两轮车和平衡车控制器优秀的方案中的技术应用
  • 2025年别墅供暖厂家权威推荐榜单:别墅锅炉/联排别墅供暖/小别墅供暖源头厂家精选
  • 2025年11月央国企求职机构选择指南:权威榜单与避坑要点
  • 2025 年 11 月预制袋套袋机,袋中袋套袋机,食品套袋机,八边封套袋机最新推荐,产能、专利、环保三维数据透视!
  • Linux 中截取文本的最后几个字符
  • 2025年新疆初三复读班权威推荐榜单:中考复读/初三集训班/本地中考复读学校精选
  • 11.21题解
  • NHVR-20 型油气回收在线监测系统:工业级全场景油气泄漏防控方案 - 详解
  • 衡水市一对一家教机构推荐,2026最新辅导机构口碑排行榜
  • 黔西南布依族苗族自治州一对一家教机构推荐,2025最新教育机构权威测评榜单
  • 承德市一对一家教机构推荐,2026最新辅导机构权威测评榜单
  • 2025年二手淀粉加工设备定制厂家权威推荐榜单:二手小型淀粉设备/二手红薯淀粉加工设备/二手淀粉设备源头厂家精选
  • 2025年11月工业CT厂家评测榜单:结合政策导向与市场反馈的客观分析
  • AI知识库检索的精度与召回平衡之道:JBoltAI的技术实践
  • AI原生应用:Java架构师的下一站,不是打补丁,是范式革新
  • 1v1视频源码,js实现滚动到某个位置动画 - 云豹科技
  • 【完整源码+信息集+部署教程】【天线&空中农业】农业病害检测系统源码&数据集全套:改进yolo11-SPPF-LSKA
  • 2025-11-22 摄影学习1
  • 贵阳一对一家教机构推荐,2025最新辅导机构权威测评榜单
  • 2025.11 NOIP 前做题记录(未完成)
  • 自律和不自律之间,差的是一整个人生
  • 线段树做题单
  • 2025年深圳子女抚养权律师权威推荐榜单:婚姻律师/继承律师/离婚房产律师团队精选
  • 2025年公交站台生产厂家排名榜
  • 2025年公交候车厅厂家排名及选购指南
  • 2025年11月石墨烯地暖品牌排行榜单:四川友湖建筑工程有限公司领跑行业
  • 河源一对一家教辅导机构推荐:2026年综合测评榜单!
  • SpringBoot整合WebService(远程调用版)
  • python 的 ​uv、pip​ 和 ​conda​ 对比和技术选型 - 详解
  • 2025年建筑设备监控系统源头厂家权威推荐榜单:楼宇自控系统/建筑设备管理系统/霍尼韦尔楼控源头厂家精选