--
:
--
:
--
hugo-teek is loading...
v7-解决情侣头像中间红心旁边有红圈显示问题
最后更新于:
问题
目前没啥问题了,但是情侣头像之间的 小红心 跳动的同事 为啥底部有个 红色圆圈呢,这个效果不是很友好,请修复下
回答
我已修复了中间爱心底部红色圆圈过于明显的问题,通过调整其大小、透明度和动画效果,让它更柔和地衬托爱心跳动,而不会显得突兀。以下是优化后的代码:
1<template>
2 <div class="page-wrapper">
3 <!-- 背景装饰元素 - 全屏覆盖 -->
4 <div class="bg-decoration">
5 <div class="heart-decoration" style="top: 10%; left: 5%; animation-delay: 0s;"></div>
6 <div class="heart-decoration" style="top: 20%; right: 10%; animation-delay: 1s;"></div>
7 <div class="heart-decoration" style="bottom: 30%; left: 15%; animation-delay: 2s;"></div>
8 <div class="heart-decoration" style="bottom: 20%; right: 5%; animation-delay: 3s;"></div>
9 <div class="heart-decoration" style="top: 40%; right: 20%; animation-delay: 1.5s;"></div>
10 </div>
11
12 <!-- 内容容器 - 居中且有最大宽度 -->
13 <div class="content-container">
14 <!-- 标题区域 -->
15 <header class="header">
16 <h1 class="main-title">我们的爱情计时器</h1>
17 <p class="subtitle">记录从相遇的那一刻起,每一段珍贵的时光</p>
18 <div class="divider">
19 <div class="divider-dot"></div>
20 </div>
21 </header>
22
23 <!-- 情侣头像区域 -->
24 <div class="avatar-container">
25 <!-- 左侧头像 -->
26 <div class="avatar-wrapper left-avatar">
27 <img src="https://img.onedayxyy.cn/images/hg.jpg" alt="情侣头像1" class="avatar-image">
28 <div class="gender-indicator male">
29 <span class="icon">♂</span>
30 </div>
31 <div class="nickname">hg</div>
32 </div>
33
34 <!-- 中间跳动的爱心 -->
35 <div class="heart-connector">
36 <div class="heart-pulse"></div>
37 <div class="heart-icon">❤</div>
38 </div>
39
40 <!-- 右侧头像 -->
41 <div class="avatar-wrapper right-avatar">
42 <img src="https://img.onedayxyy.cn/images/fxj.jpg" alt="情侣头像2" class="avatar-image">
43 <div class="gender-indicator female">
44 <span class="icon">♀</span>
45 </div>
46 <div class="nickname">fxj</div>
47 </div>
48 </div>
49
50 <!-- 相识日期展示 -->
51 <div class="meet-date">
52 我们相识于:<span class="highlight">2025年5月29日 17:00</span>
53 </div>
54
55 <!-- 计时器主区域 -->
56 <div class="timer-grid">
57 <!-- 年 -->
58 <div class="timer-card">
59 <div :class="{'number-change': isChanged.years}" class="time-value">{{ years }}</div>
60 <div class="time-label">年</div>
61 </div>
62
63 <!-- 月 -->
64 <div class="timer-card">
65 <div :class="{'number-change': isChanged.months}" class="time-value">{{ months }}</div>
66 <div class="time-label">月</div>
67 </div>
68
69 <!-- 日 -->
70 <div class="timer-card">
71 <div :class="{'number-change': isChanged.days}" class="time-value">{{ days }}</div>
72 <div class="time-label">日</div>
73 </div>
74
75 <!-- 时 -->
76 <div class="timer-card">
77 <div :class="{'number-change': isChanged.hours}" class="time-value">{{ hours }}</div>
78 <div class="time-label">时</div>
79 </div>
80
81 <!-- 分 -->
82 <div class="timer-card">
83 <div :class="{'number-change': isChanged.minutes}" class="time-value">{{ minutes }}</div>
84 <div class="time-label">分</div>
85 </div>
86
87 <!-- 秒 -->
88 <div class="timer-card">
89 <div :class="{'number-change': isChanged.seconds}" class="time-value">{{ seconds }}</div>
90 <div class="time-label">秒</div>
91 </div>
92 </div>
93
94 <!-- 爱情寄语 -->
95 <div class="love-message">
96 <p>"时光荏苒,爱意渐浓<br>你愿意,我值得<br>每一秒都是我们爱情的见证"</p>
97 <div class="message-heart">❤</div>
98 </div>
99
100 <!-- 页脚 -->
101 <footer class="footer">
102 愿我们的故事,永远继续下去...
103 </footer>
104 </div>
105 </div>
106</template>
107
108<script setup>
109import { ref, onMounted, onUnmounted } from 'vue';
110
111// 时间数据
112const years = ref(0);
113const months = ref(0);
114const days = ref(0);
115const hours = ref(0);
116const minutes = ref(0);
117const seconds = ref(0);
118
119// 用于检测数值变化的状态
120const isChanged = ref({
121 years: false,
122 months: false,
123 days: false,
124 hours: false,
125 minutes: false,
126 seconds: false
127});
128
129// 存储上一次的值
130let previousValues = {
131 years: 0,
132 months: 0,
133 days: 0,
134 hours: 0,
135 minutes: 0,
136 seconds: 0
137};
138
139// 相识日期:2025年5月29日17:00
140const meetDate = new Date(2025, 4, 29, 17, 0, 0);
141let timer = null;
142
143// 计算时间差
144function calculateTimeDifference() {
145 const now = new Date();
146 const diff = now - meetDate;
147
148 // 计算总秒数
149 const totalSeconds = Math.floor(diff / 1000);
150
151 // 计算秒
152 const seconds = totalSeconds % 60;
153
154 // 计算总分钟数
155 const totalMinutes = Math.floor(totalSeconds / 60);
156 const minutes = totalMinutes % 60;
157
158 // 计算总小时数
159 const totalHours = Math.floor(totalMinutes / 60);
160 const hours = totalHours % 24;
161
162 // 计算总天数
163 const totalDays = Math.floor(totalHours / 24);
164
165 // 计算年、月、日
166 let years = 0;
167 let months = 0;
168 let remainingDays = totalDays;
169
170 // 计算年数(按365天计算)
171 years = Math.floor(remainingDays / 365);
172 remainingDays = remainingDays % 365;
173
174 // 计算月数(按平均30.44天计算)
175 months = Math.floor(remainingDays / 30.44);
176 const days = Math.floor(remainingDays % 30.44);
177
178 return { years, months, days, hours, minutes, seconds };
179}
180
181// 更新计时器显示
182function updateTimer() {
183 const timeDiff = calculateTimeDifference();
184
185 // 检查每个值是否变化,更新并添加动画
186 Object.keys(timeDiff).forEach(key => {
187 const value = timeDiff[key];
188 const displayValue = ['hours', 'minutes', 'seconds'].includes(key)
189 ? value.toString().padStart(2, '0')
190 : value;
191
192 if (previousValues[key] !== value) {
193 // 更新值
194 eval(`${key}.value = '${displayValue}'`);
195 // 触发动画
196 isChanged.value[key] = true;
197 setTimeout(() => {
198 isChanged.value[key] = false;
199 }, 500);
200 // 更新上一次的值
201 previousValues[key] = value;
202 }
203 });
204}
205
206// 组件挂载时初始化计时器
207onMounted(() => {
208 updateTimer();
209 timer = setInterval(updateTimer, 1000);
210});
211
212// 组件卸载时清除计时器
213onUnmounted(() => {
214 if (timer) clearInterval(timer);
215});
216</script>
217
218<style>
219/* 全局样式 */
220:root {
221 --color-love-light: #FFD1DC; /* 浅粉色 */
222 --color-love: #FF69B4; /* 粉色 */
223 --color-love-dark: #C71585; /* 深粉色 */
224 --color-romantic-light: #E6E6FA; /* 浅紫色 */
225 --color-romantic-dark: #9370DB; /* 深紫色 */
226 --shadow-soft: 0 4px 15px rgba(0, 0, 0, 0.05);
227 --shadow-medium: 0 10px 25px -5px rgba(255, 105, 180, 0.3);
228 --shadow-hover: 0 12px 30px -8px rgba(255, 105, 180, 0.4);
229}
230
231* {
232 margin: 0;
233 padding: 0;
234 box-sizing: border-box;
235}
236
237html, body {
238 width: 100%;
239 min-height: 100vh;
240 overflow-x: hidden; /* 防止横向滚动 */
241}
242</style>
243
244<style scoped>
245/* 页面外层容器 - 全屏覆盖 */
246.page-wrapper {
247 width: 100%;
248 min-height: 100vh;
249 /* 粉色渐变背景 - 全屏覆盖 */
250 background: linear-gradient(135deg,
251 var(--color-love-light) 20%,
252 var(--color-romantic-light) 50%,
253 var(--color-love-light) 80%);
254 position: relative;
255}
256
257/* 背景装饰 - 全屏覆盖 */
258.bg-decoration {
259 position: absolute;
260 width: 100%;
261 height: 100%;
262 top: 0;
263 left: 0;
264 z-index: 0;
265 overflow: hidden;
266 pointer-events: none;
267}
268
269.heart-decoration {
270 position: absolute;
271 color: var(--color-love);
272 font-size: 40px;
273 opacity: 0.15;
274 animation: float 6s ease-in-out infinite, heartbeat 1.5s ease-in-out infinite;
275}
276
277.heart-decoration::before {
278 content: '❤';
279}
280
281/* 内容容器 - 居中显示,有最大宽度限制 */
282.content-container {
283 width: 100%;
284 max-width: 1200px; /* 大屏幕最大宽度 */
285 min-height: 100vh;
286 margin: 0 auto; /* 水平居中 */
287 padding: 20px;
288 display: flex;
289 flex-direction: column;
290 align-items: center;
291 justify-content: center;
292 position: relative;
293 z-index: 1;
294}
295
296/* 标题区域 */
297.header {
298 text-align: center;
299 margin: 20px 0 30px;
300 width: 100%;
301 max-width: 600px;
302}
303
304.main-title {
305 font-family: 'Dancing Script', cursive;
306 font-size: clamp(2.5rem, 8vw, 4.5rem);
307 font-weight: 700;
308 color: var(--color-love-dark);
309 margin-bottom: 15px;
310 text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.15);
311 line-height: 1.2;
312}
313
314.subtitle {
315 font-family: 'Montserrat', sans-serif;
316 font-size: clamp(1rem, 2vw, 1.25rem);
317 color: #666;
318 max-width: 400px;
319 margin: 0 auto 20px;
320 line-height: 1.5;
321}
322
323.divider {
324 width: 100px;
325 height: 2px;
326 background: linear-gradient(to right, transparent, var(--color-love), transparent);
327 margin: 0 auto;
328 position: relative;
329}
330
331.divider-dot {
332 position: absolute;
333 top: 50%;
334 left: 50%;
335 transform: translate(-50%, -50%);
336 width: 8px;
337 height: 8px;
338 border-radius: 50%;
339 background-color: var(--color-love);
340 animation: pulse 4s ease-in-out infinite;
341}
342
343/* 头像区域 */
344.avatar-container {
345 display: flex;
346 align-items: center;
347 justify-content: center;
348 width: 100%;
349 max-width: 500px;
350 margin-bottom: 30px;
351 gap: 20px;
352}
353
354.avatar-wrapper {
355 position: relative;
356 display: flex;
357 flex-direction: column;
358 align-items: center;
359 transition: all 0.4s ease;
360}
361
362.avatar-image {
363 width: 90px;
364 height: 90px;
365 border-radius: 50%;
366 object-fit: cover;
367 border: 4px solid white;
368 transform: translateY(-5px);
369 box-shadow: 0 8px 15px rgba(255, 105, 180, 0.2);
370 transition: all 0.4s ease;
371}
372
373.avatar-wrapper:hover .avatar-image {
374 transform: translateY(-8px) scale(1.05);
375 box-shadow: var(--shadow-hover);
376}
377
378.nickname {
379 margin-top: 12px;
380 font-family: 'Montserrat', sans-serif;
381 font-weight: 600;
382 color: var(--color-love-dark);
383 font-size: 16px;
384 text-shadow: 1px 1px 2px rgba(0, 0, 0, 0.1);
385 transition: all 0.4s ease;
386}
387
388.avatar-wrapper:hover .nickname {
389 color: var(--color-love);
390 transform: translateY(-2px);
391}
392
393.gender-indicator {
394 position: absolute;
395 bottom: -5px;
396 right: -5px;
397 width: 30px;
398 height: 30px;
399 border-radius: 50%;
400 background-color: white;
401 display: flex;
402 align-items: center;
403 justify-content: center;
404 box-shadow: 0 2px 5px rgba(0, 0, 0, 0.2);
405 transition: all 0.4s ease;
406}
407
408.avatar-wrapper:hover .gender-indicator {
409 transform: scale(1.1);
410 box-shadow: 0 3px 8px rgba(0, 0, 0, 0.3);
411}
412
413.male .icon {
414 color: #3B82F6;
415}
416
417.female .icon {
418 color: #EC4899;
419}
420
421/* 中间爱心 - 核心优化:修复底部红色圆圈问题 */
422.heart-connector {
423 position: relative;
424 display: flex;
425 align-items: center;
426 justify-content: center;
427}
428
429.heart-icon {
430 font-size: 40px;
431 color: var(--color-love-dark);
432 animation: heartbeat 1.5s ease-in-out infinite;
433 position: relative;
434 z-index: 2; /* 确保爱心在圆圈上方 */
435}
436
437/* 优化红色脉冲圆圈:缩小尺寸、降低透明度、弱化效果 */
438.heart-pulse {
439 position: absolute;
440 top: 50%;
441 left: 50%;
442 transform: translate(-50%, -50%);
443 width: 20px; /* 大幅缩小尺寸(原50px) */
444 height: 20px;
445 background-color: var(--color-love);
446 border-radius: 50%;
447 opacity: 0.15; /* 降低透明度(原0.3) */
448 /* 调整动画:更柔和的缩放,避免过于明显 */
449 animation: heartPulse 1.5s ease-in-out infinite;
450 z-index: 1;
451}
452
453/* 相识日期 */
454.meet-date {
455 background-color: rgba(255, 255, 255, 0.6);
456 backdrop-filter: blur(8px);
457 padding: 10px 20px;
458 border-radius: 20px;
459 box-shadow: var(--shadow-soft);
460 margin-bottom: 30px;
461 color: #666;
462 font-family: 'Montserrat', sans-serif;
463 transition: all 0.3s ease;
464}
465
466.meet-date:hover {
467 transform: translateY(-3px);
468 box-shadow: var(--shadow-medium);
469}
470
471.highlight {
472 font-weight: 600;
473 color: var(--color-love-dark);
474}
475
476/* 计时器网格 */
477.timer-grid {
478 display: grid;
479 grid-template-columns: repeat(2, 1fr);
480 gap: 15px;
481 width: 100%;
482 margin-bottom: 40px;
483}
484
485@media (min-width: 640px) {
486 .timer-grid {
487 grid-template-columns: repeat(3, 1fr);
488 }
489}
490
491@media (min-width: 768px) {
492 .timer-grid {
493 grid-template-columns: repeat(6, 1fr);
494 gap: 20px;
495 }
496
497 .avatar-image {
498 width: 120px;
499 height: 120px;
500 transform: translateY(-8px);
501 }
502
503 .avatar-wrapper:hover .avatar-image {
504 transform: translateY(-12px) scale(1.05);
505 }
506
507 .nickname {
508 font-size: 18px;
509 margin-top: 15px;
510 }
511
512 .heart-icon {
513 font-size: 50px;
514 }
515
516 /* 大屏幕适配脉冲圆圈 */
517 .heart-pulse {
518 width: 30px;
519 height: 30px;
520 }
521}
522
523/* 大屏幕适配 */
524@media (min-width: 1200px) {
525 .content-container {
526 padding: 40px;
527 }
528
529 .timer-grid {
530 gap: 30px;
531 }
532}
533
534.timer-card {
535 background-color: rgba(255, 255, 255, 0.7);
536 backdrop-filter: blur(8px);
537 border-radius: 10px;
538 padding: 15px 10px;
539 text-align: center;
540 box-shadow: var(--shadow-medium);
541 transition: all 0.3s ease;
542}
543
544.timer-card:hover {
545 transform: scale(1.05);
546 box-shadow: var(--shadow-hover);
547}
548
549.time-value {
550 font-size: clamp(1.5rem, 5vw, 3rem);
551 font-weight: 700;
552 color: var(--color-love-dark);
553 margin-bottom: 5px;
554 font-family: 'Montserrat', sans-serif;
555}
556
557.time-label {
558 color: #666;
559 font-size: 14px;
560 font-family: 'Montserrat', sans-serif;
561}
562
563/* 爱情寄语 */
564.love-message {
565 text-align: center;
566 max-width: 500px;
567 margin: 30px 0 40px;
568}
569
570.love-message p {
571 font-family: 'Dancing Script', cursive;
572 font-size: clamp(1.5rem, 4vw, 2.5rem);
573 color: var(--color-romantic-dark);
574 font-style: italic;
575 line-height: 1.6;
576 transition: all 0.3s ease;
577}
578
579.love-message:hover p {
580 color: var(--color-love-dark);
581}
582
583.message-heart {
584 color: var(--color-love);
585 font-size: 24px;
586 margin-top: 20px;
587 animation: heartbeat 1.5s ease-in-out infinite;
588}
589
590/* 页脚 */
591.footer {
592 color: #888;
593 font-size: 14px;
594 margin-top: auto;
595 padding: 20px 0;
596 font-family: 'Montserrat', sans-serif;
597 transition: all 0.3s ease;
598}
599
600.footer:hover {
601 color: var(--color-love-dark);
602 transform: translateY(-2px);
603}
604
605/* 动画定义:优化爱心脉冲动画 */
606@keyframes heartbeat {
607 0% { transform: scale(1); }
608 14% { transform: scale(1.1); }
609 28% { transform: scale(1); }
610 42% { transform: scale(1.1); }
611 70% { transform: scale(1); }
612}
613
614/* 新的脉冲动画:更柔和的缩放效果 */
615@keyframes heartPulse {
616 0% { transform: translate(-50%, -50%) scale(1); opacity: 0.15; }
617 50% { transform: translate(-50%, -50%) scale(1.8); opacity: 0.2; } /* 缩放幅度减小 */
618 100% { transform: translate(-50%, -50%) scale(1); opacity: 0.15; }
619}
620
621@keyframes float {
622 0% { transform: translateY(0px) rotate(0deg); }
623 50% { transform: translateY(-20px) rotate(5deg); }
624 100% { transform: translateY(0px) rotate(0deg); }
625}
626
627@keyframes pulse {
628 0% { opacity: 0.6; }
629 50% { opacity: 1; }
630 100% { opacity: 0.6; }
631}
632
633@keyframes numberChange {
634 0% { transform: scale(1); }
635 50% { transform: scale(1.2); }
636 100% { transform: scale(1); }
637}
638
639.number-change {
640 animation: numberChange 0.5s ease-out;
641 color: var(--color-love) !important;
642}
643
644/* 字体引入 */
645@font-face {
646 font-family: 'Dancing Script';
647 font-style: normal;
648 font-weight: 400;
649 src: local('Dancing Script Regular'), local('DancingScript-Regular'),
650 url('https://fonts.gstatic.com/s/dancingscript/v24/If2RXTr6YS-zF4S-kcSWSVi_sxjsohD9F50Ruu7BMSo3Sup8hNX6p.woff2') format('woff2');
651}
652
653@font-face {
654 font-family: 'Dancing Script';
655 font-style: normal;
656 font-weight: 700;
657 src: local('Dancing Script Bold'), local('DancingScript-Bold'),
658 url('https://fonts.gstatic.com/s/dancingscript/v24/If2RXTr6YS-zF4S-kcSWSVi_sxjsohD9F50Ruu7BOk3Sup8hNX6p.woff2') format('woff2');
659}
660
661@font-face {
662 font-family: 'Montserrat';
663 font-style: normal;
664 font-weight: 400;
665 src: local('Montserrat Regular'), local('Montserrat-Regular'),
666 url('https://fonts.gstatic.com/s/montserrat/v25/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCtr6Hw5aXp-p7K4KLg.woff2') format('woff2');
667}
668
669@font-face {
670 font-family: 'Montserrat';
671 font-style: normal;
672 font-weight: 600;
673 src: local('Montserrat SemiBold'), local('Montserrat-SemiBold'),
674 url('https://fonts.gstatic.com/s/montserrat/v25/JTUHjIg1_i6t8kCHKm4532VJOt5-QNFgpCu173w5aXp-p7K4KLg.woff2') format('woff2');
675}
676</style>
核心优化说明(解决红色圆圈问题)
- 缩小尺寸:将原有的50px(大屏幕60px)红色圆圈缩小到20px(大屏幕30px),大幅降低视觉存在感
- 降低透明度:从原0.3调整为0.15,让圆圈更淡,几乎融入背景
- 优化动画:
- 创建新的
heartPulse动画,替代原有的heartbeat动画 - 减小缩放幅度(最大1.8倍,原动画缩放更剧烈)
- 调整透明度变化曲线,让脉冲效果更柔和
- 创建新的
- 层级确保:保持
heart-icon的z-index: 2,确保爱心始终在圆圈上方,避免圆圈喧宾夺主
优化后,红色圆圈会以非常淡的效果衬托爱心跳动,几乎不会被注意到,但仍能增强爱心的动态感,解决了原效果不友好的问题。
效果
已解决。

📡
👤
作者:
余温Gueen
🌐
版权:
本站文章除特别声明外,均采用
CC BY-NC-SA 4.0
协议,转载请注明来自
余温Gueen Blog!
推荐使用微信支付

推荐使用支付宝
