外观
圣诞快乐
约 43 字小于 1 分钟
2025-12-24
<template>
<div class="christmas-page">
<!-- 隐藏的音频元素 -->
<audio ref="audioRef" :src="musicSrc" loop></audio>
<!-- 雪花容器:持续添加新雪花,无间隙 -->
<div class="snow-container">
<div
v-for="(snow, index) in snowflakes"
:key="index"
class="snowflake"
:style="{
left: snow.left,
width: snow.width,
height: snow.height,
animationDuration: snow.animationDuration,
animationDelay: snow.animationDelay,
opacity: snow.opacity
}"
></div>
</div>
<!-- 强制居中的卡片 -->
<div class="card">
<!-- 音乐控制按钮移到卡片内部右上角 -->
<div class="music-control" @click="toggleMusic">
<span v-if="isMusicPlaying">🔇</span>
<span v-else>🔊</span>
</div>
<div class="tree-decoration">🎄</div>
<h1>圣诞快乐 ❤️</h1>
<p class="subtitle">Merry Christmas & Happy New Year</p>
<p class="msg">
这个圣诞,没有漫天烟火也没关系<br>
只要身边是你,就胜过所有浪漫
</p>
<div>
<p>1790茶咖相遇</p>
<img src="https://wugz1995.oss-cn-guangzhou.aliyuncs.com/%E5%9B%BE%E7%89%87/%E5%8D%9A%E5%AE%A2/1790.png" alt="1790茶咖" style="width: 300px;">
</div>
<div>
<p>玩《双影奇境》</p>
<img src="https://wugz1995.oss-cn-guangzhou.aliyuncs.com/%E5%9B%BE%E7%89%87/%E5%8D%9A%E5%AE%A2/%E7%94%9F%E6%88%90%E6%B8%B8%E6%88%8F%E5%9C%BA%E6%99%AF%E7%94%BB.png" alt="PS5" style="width: 300px;">
</div>
<div>
<p>德思勤玩密室逃脱</p>
<img src="https://wugz1995.oss-cn-guangzhou.aliyuncs.com/%E5%9B%BE%E7%89%87/%E5%8D%9A%E5%AE%A2/%E5%AF%86%E5%AE%A4%E9%80%83%E8%84%B1.png" alt="密室逃脱" style="width: 300px;">
</div>
<div>
<p>看《疯狂动物城》</p>
<img src="https://wugz1995.oss-cn-guangzhou.aliyuncs.com/%E5%9B%BE%E7%89%87/%E5%8D%9A%E5%AE%A2/%E7%9C%8B%E7%94%B5%E5%BD%B1.png" alt="看电影" style="width: 300px;">
</div>
<button class="btn" @click="isModalShow = true" style="margin-top: 20px;">点我有惊喜</button>
<div class="bell-decoration">🔔</div>
</div>
<!-- 弹窗 -->
<div class="modal" v-show="isModalShow">
<div class="modal-content">
<h2>我喜欢你!</h2>
<p>愿意和我一起,把每个圣诞都过成我们的纪念日吗?</p>
<button class="btn" @click="isModalShow = false">好呀 ❤️</button>
</div>
</div>
</div>
</template>
<script setup>
import { ref, onMounted } from 'vue';
const isModalShow = ref(false);
const snowflakes = ref([]); // 雪花数组(持续添加新雪花)
// 音乐相关变量
const audioRef = ref(null);
const isMusicPlaying = ref(false);
// 这里使用了一个圣诞音乐的链接,你可以替换为你自己的音乐文件
const musicSrc = ref('https://wugz1995.oss-cn-guangzhou.aliyuncs.com/%E5%9B%BE%E7%89%87/%E5%8D%9A%E5%AE%A2/All%20I%20Want%20For%20Christmas%20Is%20You.mp3');
// 播放/暂停音乐
const toggleMusic = () => {
if (isMusicPlaying.value) {
audioRef.value.pause();
isMusicPlaying.value = false;
} else {
audioRef.value.play();
isMusicPlaying.value = true;
}
};
// 持续添加新雪花(不替换数组,避免间隙)
const addSnowflakes = () => {
const newSnowCount = 10; // 每次添加10片雪花
const maxSnowCount = 500; // 最多保留500片(避免性能问题)
// 生成新雪花
for (let i = 0; i < newSnowCount; i++) {
snowflakes.value.push({
left: `${Math.random() * 100}vw`,
width: `${Math.random() * 6 + 3}px`,
height: `${Math.random() * 6 + 3}px`,
animationDuration: `${Math.random() * 15 + 25}s`,
animationDelay: `${Math.random() * 2}s`,
opacity: Math.random() * 0.7 + 0.3
});
}
// 超过最大数量时,移除最早的雪花(避免数组无限增大)
if (snowflakes.value.length > maxSnowCount) {
snowflakes.value.splice(0, newSnowCount);
}
};
// 自动播放音乐
const autoPlayMusic = () => {
audioRef.value.play();
isMusicPlaying.value = true;
};
// 初始化+持续添加雪花(每2秒加一批,实现"源源不断")
onMounted(() => {
// 每2秒添加新雪花,无间隙
setInterval( ()=>{addSnowflakes();}, 200);
});
</script>
<style scoped>
/* 页面容器:强制全屏+居中,覆盖Vuepress默认样式 */
.christmas-page {
position: relative;
/* width: 100vw !important; */
height: 160vh !important;
margin: 0 !important;
padding: 0 !important;
background: linear-gradient(135deg, #ffccd5 0%, #ffe5ec 100%);
display: flex !important;
justify-content: center !important;
align-items: center !important;
overflow: hidden;
}
/* 音乐控制按钮样式 */
.music-control {
position: relative;
top: 20px;
left: 10px;
width: 50px;
height: 50px;
border-radius: 50%;
background: rgba(255, 255, 255, 0.8);
display: flex;
justify-content: center;
align-items: center;
cursor: pointer;
z-index: 1000;
font-size: 24px;
box-shadow: 0 2px 10px rgba(0, 0, 0, 0.1);
transition: all 0.3s ease;
}
.music-control:hover {
transform: scale(1.1);
background: white;
}
/* 如果音乐正在播放,添加动画效果 */
.music-control:not(.paused) {
animation: pulse 1.5s infinite;
}
@keyframes pulse {
0% { box-shadow: 0 0 0 0 rgba(216, 31, 38, 0.7); }
70% { box-shadow: 0 0 0 10px rgba(216, 31, 38, 0); }
100% { box-shadow: 0 0 0 0 rgba(216, 31, 38, 0); }
}
/* 雪花容器:全屏覆盖 */
.snow-container {
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 1;
}
/* 雪花样式:持续下落 */
.snowflake {
position: absolute;
top: -10px;
background: #ffffff;
border-radius: 50%;
animation: snow-fall linear infinite;
/* 添加随机的左右摇摆效果 */
transform-origin: center;
}
/* 雪花下落动画 - 丰富效果 */
@keyframes snow-fall {
0% {
transform: translateY(0) rotate(0deg) translateX(0) rotateZ(0deg);
opacity: 1;
}
25% {
transform: translateY(50vh) rotate(90deg) translateX(10px) rotateZ(90deg);
}
50% {
transform: translateY(100vh) rotate(180deg) translateX(0) rotateZ(180deg);
}
75% {
transform: translateY(150vh) rotate(270deg) translateX(-10px) rotateZ(270deg);
}
100% {
transform: translateY(200vh) rotate(360deg) translateX(0) rotateZ(360deg);
opacity: 0;
}
}
/* 卡片:强制居中+固定宽度 */
.card {
position: relative;
background: #fff;
padding: 40px 30px;
border-radius: 20px;
text-align: center;
width: 380px; /* 固定窄宽度 */
box-shadow: 0 5px 20px rgba(255, 100, 120, 0.15);
z-index: 10;
/* 额外确保居中(防止flex失效) */
margin: 0 auto;
}
/* 装饰元素 */
.tree-decoration {
position: absolute;
top: -20px;
left: -20px;
font-size: 35px;
}
.bell-decoration {
position: absolute;
bottom: -15px;
right: -15px;
font-size: 25px;
}
/* 文字&按钮 */
.card h1 {
color: #d81f26;
font-size: 28px;
margin-bottom: 8px;
}
.card .subtitle {
color: #666;
font-size: 16px;
margin-bottom: 25px;
}
.card .msg {
color: #333;
font-size: 18px;
line-height: 1.7;
margin-bottom: 35px;
}
.btn {
padding: 14px 35px;
background: #d81f26;
color: #fff;
border: none;
border-radius: 50px;
font-size: 17px;
cursor: pointer;
transition: transform 0.3s;
}
.btn:hover {
transform: scale(1.05);
}
/* 弹窗 */
.modal {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.7);
display: flex;
justify-content: center;
/* end 等价于 flex-end,保持内容水平居中、垂直靠下的对齐方向 */
align-items: end;
z-index: 100;
/* 关键:添加底部内边距,让内容上移100px */
padding-bottom: 18.52vh;
/* 必加:防止padding撑开容器高度(100%高度包含padding) */
box-sizing: border-box;
}
.modal-content {
background: #fff;
padding: 40px;
border-radius: 20px;
text-align: center;
width: 350px;
}
</style>版权所有
版权归属:wgz1995