From 85e98216a566f406746358f27d94b183c3877ead Mon Sep 17 00:00:00 2001 From: chayunyolong Date: Thu, 8 Feb 2024 18:25:19 +0800 Subject: [PATCH] =?UTF-8?q?=E9=87=8D=E6=9E=84=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- {assets => NewYear/assets}/a.png | Bin index.html => NewYear/index.html | 32 +-- script.js => NewYear/script.js | 382 +++++++++++++++---------------- styles.css => NewYear/styles.css | 112 ++++----- 4 files changed, 263 insertions(+), 263 deletions(-) rename {assets => NewYear/assets}/a.png (100%) rename index.html => NewYear/index.html (94%) rename script.js => NewYear/script.js (97%) rename styles.css => NewYear/styles.css (95%) diff --git a/assets/a.png b/NewYear/assets/a.png similarity index 100% rename from assets/a.png rename to NewYear/assets/a.png diff --git a/index.html b/NewYear/index.html similarity index 94% rename from index.html rename to NewYear/index.html index 97abb25..18c8823 100644 --- a/index.html +++ b/NewYear/index.html @@ -1,16 +1,16 @@ - - - - - 新年倒计时 - - - -
距离新年还有:00:00:00
- - - - - - - + + + + + 新年倒计时 + + + +
距离新年还有:00:00:00
+ + + + + + + \ No newline at end of file diff --git a/script.js b/NewYear/script.js similarity index 97% rename from script.js rename to NewYear/script.js index ce17186..ec62003 100644 --- a/script.js +++ b/NewYear/script.js @@ -1,191 +1,191 @@ -// 粒子类定义 -class Particle { - // 粒子构造函数 - constructor(x, y, radius, color, velocity, decay, gravity) { - this.x = x; // 粒子的x坐标 - this.y = y; // 粒子的y坐标 - this.radius = radius; // 粒子的半径 - this.color = color; // 粒子的颜色 - this.velocity = velocity; // 粒子的速度对象,包含x和y方向的速度 - this.decay = decay || 0.015; // 粒子的衰减速率,默认值为0.015 - this.alpha = 1; // 粒子的透明度,初始值为1 - this.gravity = gravity || 0.05; // 粒子受到的重力加速度,默认值为0.05 - } - - // 绘制粒子的方法 - draw() { - ctx.save(); // 保存当前绘图状态 - ctx.globalAlpha = this.alpha; // 设置绘图透明度 - ctx.beginPath(); // 开始绘制 - ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false); // 绘制圆形粒子 - ctx.fillStyle = this.color; // 设置填充颜色 - ctx.fill(); // 填充颜色 - ctx.restore(); // 恢复之前保存的绘图状态 - } - - // 更新粒子状态的方法 - update() { - this.velocity.y += this.gravity; // 应用重力,使粒子下降 - this.x += this.velocity.x; // 更新粒子的x坐标 - this.y += this.velocity.y; // 更新粒子的y坐标 - this.alpha -= this.decay; // 更新粒子的透明度 - if (this.alpha <= this.decay) { - this.alpha = 0; // 当透明度小于衰减速率时,将透明度设置为0 - } - this.draw(); // 绘制更新后的粒子 - } - - // 判断粒子是否仍然存活(透明度大于0) - isAlive() { - return this.alpha > 0; - } -} - -// 烟花类定义 -class Firework { - // 烟花构造函数 - constructor(x, y, color, riseSpeed = -1, particleSize = 2) { - this.x = x; // 烟花的x坐标 - this.y = y; // 烟花的y坐标 - this.color = color; // 烟花的颜色 - this.riseSpeed = riseSpeed; // 烟花上升速度 - this.particleSize = particleSize; // 爆炸后生成的粒子大小 - this.particles = []; // 存储爆炸后生成的粒子数组 - this.exploded = false; // 标记烟花是否已经爆炸 - this.velocity = { x: Math.random() * 2 - 1, y: this.riseSpeed }; // 烟花的速度,x轴速度模拟风 - } - - // 烟花爆炸方法 - explode() { - const particleCount = 100 + Math.random() * 1000; // 确定爆炸生成的粒子数量 - for (let i = 0; i < particleCount; i++) { - const speed = Math.random() * 5 + 2; // 粒子速度 - const decay = Math.random() * 0.04 + 0.01; // 粒子衰减速率 - const gravity = Math.random() * 0.05 + 0.03; // 粒子重力加速度 - // 创建新粒子并添加到粒子数组中 - this.particles.push(new Particle(this.x, this.y, this.particleSize, `hsl(${Math.random() * 360}, 100%, 50%)`, { - x: Math.cos(Math.PI * 2 * i / particleCount) * speed, - y: Math.sin(Math.PI * 2 * i / particleCount) * speed - }, decay, gravity)); - } - } - - // 更新烟花状态的方法 - update() { - if (!this.exploded) { - this.y += this.velocity.y; // 更新烟花的y坐标,使其上升 - this.x += this.velocity.x; // 更新烟花的x坐标,模拟风效果 - this.draw(); // 绘制上升中的烟花 - - // 判断烟花是否达到爆炸高度 - if (this.y < canvas.height * (0.18 + Math.random() * 0.22)) { - this.exploded = true; // 标记烟花为已爆炸 - this.explode(); // 触发烟花爆炸 - } - } else { - // 更新所有粒子的状态,并移除已经“死亡”的粒子 - this.particles = this.particles.filter(p => p.isAlive()); - this.particles.forEach(p => p.update()); - } - } - - // 绘制上升中的烟花方法 - draw() { - ctx.save(); // 保存当前绘图状态 - ctx.globalAlpha = 1; // 设置绘图透明度为不透明 - ctx.beginPath(); // 开始绘制 - ctx.arc(this.x, this.y, 2, 0, Math.PI * 2, false); // 绘制表示烟花的小圆点 - ctx.fillStyle = this.color; // 设置填充颜色 - ctx.fill(); // 填充颜色 - ctx.restore(); // 恢复之前保存的绘图状态 - } -} - -// 获取canvas元素并设置其宽高 -const canvas = document.getElementById('fireworksCanvas'); -const ctx = canvas.getContext('2d'); -canvas.width = window.innerWidth; -canvas.height = window.innerHeight; - -let fireworks = []; // 存储所有烟花的数组 - -// 动画循环函数,用于不断更新画布上的内容 -function animate() { - requestAnimationFrame(animate); // 请求下一帧动画 - ctx.fillStyle = 'rgba(0, 0, 0, 0.1)'; // 设置画布覆盖颜色(用于创建尾迹效果) - ctx.fillRect(0, 0, canvas.width, canvas.height); // 覆盖整个画布 - - // 遍历所有烟花,更新它们的状态,并在必要时将它们从数组中移除 - fireworks.forEach((firework, index) => { - firework.update(); - if (firework.exploded && firework.particles.length === 0) { - fireworks.splice(index, 1); // 移除已经爆炸且粒子消失的烟花 - } - }); -} - -// 创建新烟花的函数,用于在画布上添加新的烟花 -function createFirework() { - const x = Math.random() * canvas.width; // 在画布宽度范围内随机选择x坐标 - const y = canvas.height; // y坐标设置为画布底部 - const color = `hsl(${Math.random() * 360}, 100%, 50%)`; // 随机选择颜色 - const riseSpeed = -Math.random() * 8 + 1; // 随机生成上升速度 - const particleSize = Math.random() * 3 + 2; // 随机生成粒子大小 - // 创建新的烟花并添加到烟花数组中 - fireworks.push(new Firework(x, y, color, riseSpeed, particleSize)); -} - -function launchFireworks() { - const initialFireworks = 10; // 第一次触发时的烟花数量 - - // 立即生成初始数量的烟花粒子 - for (let i = 0; i < initialFireworks; i++) { - createFirework(); - } - - // 定时生成新的烟花粒子 - const interval = setInterval(() => { - createFirework(); - // 可以在这里添加逻辑来停止生成新的烟花粒子,例如设置一个生成烟花的总数限制 - }, 1000); // 每隔1秒生成一个新的烟花粒子 -} - -// 为预览按钮添加点击事件监听器,用于测试烟花效果 -document.getElementById('previewButton').addEventListener('click', launchFireworks); - -// 触发烟花效果的函数,用于在特定条件下(如倒计时结束)启动一系列烟花 -function triggerFireworks() { - const fireworksCount = 5; // 定义触发的烟花数量 - for (let i = 0; i < fireworksCount; i++) { - // 每隔一秒触发一个烟花,创建连续的烟花效果 - setTimeout(createFirework, i * 1000); - } -} - -// 倒计时逻辑,假设倒计时结束后触发烟花 -const countdownElement = document.getElementById('countdown'); -const targetDate = new Date('Feb 9, 2024 23:59:59').getTime(); - -// 倒计时更新函数,用于显示距离目标日期的时间并在到达时触发烟花 -function updateCountdown() { - const now = new Date().getTime(); // 获取当前时间 - const distance = targetDate - now; // 计算距离目标日期的时间差 - // 计算天、小时、分钟和秒 - const days = Math.floor(distance / (1000 * 60 * 60 * 24)); - const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); - const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)); - const seconds = Math.floor((distance % (1000 * 60)) / 1000); - // 更新倒计时显示 - countdownElement.innerHTML = `距离新年还有:${days}天${hours}小时${minutes}分${seconds}秒`; - - // 如果时间差小于0,说明目标日期已到达 - if (distance < 0) { - clearInterval(interval); // 停止倒计时更新 - countdownElement.style.display = 'none'; // 隐藏倒计时显示 - launchFireworks(); // 使用 launchFireworks 函数触发烟花效果 - } -} - -const interval = setInterval(updateCountdown, 1000); // 每秒更新倒计时 - -animate(); // 开始动画循环 +// 粒子类定义 +class Particle { + // 粒子构造函数 + constructor(x, y, radius, color, velocity, decay, gravity) { + this.x = x; // 粒子的x坐标 + this.y = y; // 粒子的y坐标 + this.radius = radius; // 粒子的半径 + this.color = color; // 粒子的颜色 + this.velocity = velocity; // 粒子的速度对象,包含x和y方向的速度 + this.decay = decay || 0.015; // 粒子的衰减速率,默认值为0.015 + this.alpha = 1; // 粒子的透明度,初始值为1 + this.gravity = gravity || 0.05; // 粒子受到的重力加速度,默认值为0.05 + } + + // 绘制粒子的方法 + draw() { + ctx.save(); // 保存当前绘图状态 + ctx.globalAlpha = this.alpha; // 设置绘图透明度 + ctx.beginPath(); // 开始绘制 + ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2, false); // 绘制圆形粒子 + ctx.fillStyle = this.color; // 设置填充颜色 + ctx.fill(); // 填充颜色 + ctx.restore(); // 恢复之前保存的绘图状态 + } + + // 更新粒子状态的方法 + update() { + this.velocity.y += this.gravity; // 应用重力,使粒子下降 + this.x += this.velocity.x; // 更新粒子的x坐标 + this.y += this.velocity.y; // 更新粒子的y坐标 + this.alpha -= this.decay; // 更新粒子的透明度 + if (this.alpha <= this.decay) { + this.alpha = 0; // 当透明度小于衰减速率时,将透明度设置为0 + } + this.draw(); // 绘制更新后的粒子 + } + + // 判断粒子是否仍然存活(透明度大于0) + isAlive() { + return this.alpha > 0; + } +} + +// 烟花类定义 +class Firework { + // 烟花构造函数 + constructor(x, y, color, riseSpeed = -1, particleSize = 2) { + this.x = x; // 烟花的x坐标 + this.y = y; // 烟花的y坐标 + this.color = color; // 烟花的颜色 + this.riseSpeed = riseSpeed; // 烟花上升速度 + this.particleSize = particleSize; // 爆炸后生成的粒子大小 + this.particles = []; // 存储爆炸后生成的粒子数组 + this.exploded = false; // 标记烟花是否已经爆炸 + this.velocity = { x: Math.random() * 2 - 1, y: this.riseSpeed }; // 烟花的速度,x轴速度模拟风 + } + + // 烟花爆炸方法 + explode() { + const particleCount = 100 + Math.random() * 1000; // 确定爆炸生成的粒子数量 + for (let i = 0; i < particleCount; i++) { + const speed = Math.random() * 5 + 2; // 粒子速度 + const decay = Math.random() * 0.04 + 0.01; // 粒子衰减速率 + const gravity = Math.random() * 0.05 + 0.03; // 粒子重力加速度 + // 创建新粒子并添加到粒子数组中 + this.particles.push(new Particle(this.x, this.y, this.particleSize, `hsl(${Math.random() * 360}, 100%, 50%)`, { + x: Math.cos(Math.PI * 2 * i / particleCount) * speed, + y: Math.sin(Math.PI * 2 * i / particleCount) * speed + }, decay, gravity)); + } + } + + // 更新烟花状态的方法 + update() { + if (!this.exploded) { + this.y += this.velocity.y; // 更新烟花的y坐标,使其上升 + this.x += this.velocity.x; // 更新烟花的x坐标,模拟风效果 + this.draw(); // 绘制上升中的烟花 + + // 判断烟花是否达到爆炸高度 + if (this.y < canvas.height * (0.18 + Math.random() * 0.22)) { + this.exploded = true; // 标记烟花为已爆炸 + this.explode(); // 触发烟花爆炸 + } + } else { + // 更新所有粒子的状态,并移除已经“死亡”的粒子 + this.particles = this.particles.filter(p => p.isAlive()); + this.particles.forEach(p => p.update()); + } + } + + // 绘制上升中的烟花方法 + draw() { + ctx.save(); // 保存当前绘图状态 + ctx.globalAlpha = 1; // 设置绘图透明度为不透明 + ctx.beginPath(); // 开始绘制 + ctx.arc(this.x, this.y, 2, 0, Math.PI * 2, false); // 绘制表示烟花的小圆点 + ctx.fillStyle = this.color; // 设置填充颜色 + ctx.fill(); // 填充颜色 + ctx.restore(); // 恢复之前保存的绘图状态 + } +} + +// 获取canvas元素并设置其宽高 +const canvas = document.getElementById('fireworksCanvas'); +const ctx = canvas.getContext('2d'); +canvas.width = window.innerWidth; +canvas.height = window.innerHeight; + +let fireworks = []; // 存储所有烟花的数组 + +// 动画循环函数,用于不断更新画布上的内容 +function animate() { + requestAnimationFrame(animate); // 请求下一帧动画 + ctx.fillStyle = 'rgba(0, 0, 0, 0.1)'; // 设置画布覆盖颜色(用于创建尾迹效果) + ctx.fillRect(0, 0, canvas.width, canvas.height); // 覆盖整个画布 + + // 遍历所有烟花,更新它们的状态,并在必要时将它们从数组中移除 + fireworks.forEach((firework, index) => { + firework.update(); + if (firework.exploded && firework.particles.length === 0) { + fireworks.splice(index, 1); // 移除已经爆炸且粒子消失的烟花 + } + }); +} + +// 创建新烟花的函数,用于在画布上添加新的烟花 +function createFirework() { + const x = Math.random() * canvas.width; // 在画布宽度范围内随机选择x坐标 + const y = canvas.height; // y坐标设置为画布底部 + const color = `hsl(${Math.random() * 360}, 100%, 50%)`; // 随机选择颜色 + const riseSpeed = -Math.random() * 8 + 1; // 随机生成上升速度 + const particleSize = Math.random() * 3 + 2; // 随机生成粒子大小 + // 创建新的烟花并添加到烟花数组中 + fireworks.push(new Firework(x, y, color, riseSpeed, particleSize)); +} + +function launchFireworks() { + const initialFireworks = 10; // 第一次触发时的烟花数量 + + // 立即生成初始数量的烟花粒子 + for (let i = 0; i < initialFireworks; i++) { + createFirework(); + } + + // 定时生成新的烟花粒子 + const interval = setInterval(() => { + createFirework(); + // 可以在这里添加逻辑来停止生成新的烟花粒子,例如设置一个生成烟花的总数限制 + }, 1000); // 每隔1秒生成一个新的烟花粒子 +} + +// 为预览按钮添加点击事件监听器,用于测试烟花效果 +document.getElementById('previewButton').addEventListener('click', launchFireworks); + +// 触发烟花效果的函数,用于在特定条件下(如倒计时结束)启动一系列烟花 +function triggerFireworks() { + const fireworksCount = 5; // 定义触发的烟花数量 + for (let i = 0; i < fireworksCount; i++) { + // 每隔一秒触发一个烟花,创建连续的烟花效果 + setTimeout(createFirework, i * 1000); + } +} + +// 倒计时逻辑,假设倒计时结束后触发烟花 +const countdownElement = document.getElementById('countdown'); +const targetDate = new Date('Feb 9, 2024 23:59:59').getTime(); + +// 倒计时更新函数,用于显示距离目标日期的时间并在到达时触发烟花 +function updateCountdown() { + const now = new Date().getTime(); // 获取当前时间 + const distance = targetDate - now; // 计算距离目标日期的时间差 + // 计算天、小时、分钟和秒 + const days = Math.floor(distance / (1000 * 60 * 60 * 24)); + const hours = Math.floor((distance % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60)); + const minutes = Math.floor((distance % (1000 * 60 * 60)) / (1000 * 60)); + const seconds = Math.floor((distance % (1000 * 60)) / 1000); + // 更新倒计时显示 + countdownElement.innerHTML = `距离新年还有:${days}天${hours}小时${minutes}分${seconds}秒`; + + // 如果时间差小于0,说明目标日期已到达 + if (distance < 0) { + clearInterval(interval); // 停止倒计时更新 + countdownElement.style.display = 'none'; // 隐藏倒计时显示 + launchFireworks(); // 使用 launchFireworks 函数触发烟花效果 + } +} + +const interval = setInterval(updateCountdown, 1000); // 每秒更新倒计时 + +animate(); // 开始动画循环 diff --git a/styles.css b/NewYear/styles.css similarity index 95% rename from styles.css rename to NewYear/styles.css index 882aa3b..589d656 100644 --- a/styles.css +++ b/NewYear/styles.css @@ -1,56 +1,56 @@ -body, html { - width: 100%; - height: 100%; - margin: 0; - overflow: hidden; - min-height: 100%; /* 确保至少有100%的高度 */ -} - -body { - font-family: 'Arial', sans-serif; - background-image: url('../new-year-countdown/assets/a.png'); - background-size: cover; - background-position: center; /* 确保背景图片居中显示 */ - color: #f5f5f5; -} - -#countdown, #greetings, #previewButton { - position: relative; - z-index: 2; /* 确保这些元素在canvas之上 */ -} - -#countdown { - font-size: 36px; - text-align: center; - margin: 50px 0; -} - -#previewButton { - display: block; - width: 200px; - margin: 20px auto; - padding: 10px; - font-size: 16px; - cursor: pointer; - background-color: #4CAF50; - color: white; - border: none; - border-radius: 5px; -} - -#greetings { - font-size: 32px; - text-align: center; - margin-top: 20px; -} - -#fireworksCanvas { - background: transparent; - position: absolute; - top: 0; - left: 0; - width: 100%; - height: 100%; - z-index: 1; - pointer-events: none; /* 允许鼠标事件穿透canvas */ -} +body, html { + width: 100%; + height: 100%; + margin: 0; + overflow: hidden; + min-height: 100%; /* 确保至少有100%的高度 */ +} + +body { + font-family: 'Arial', sans-serif; + background-image: url('../new-year-countdown/assets/a.png'); + background-size: cover; + background-position: center; /* 确保背景图片居中显示 */ + color: #f5f5f5; +} + +#countdown, #greetings, #previewButton { + position: relative; + z-index: 2; /* 确保这些元素在canvas之上 */ +} + +#countdown { + font-size: 36px; + text-align: center; + margin: 50px 0; +} + +#previewButton { + display: block; + width: 200px; + margin: 20px auto; + padding: 10px; + font-size: 16px; + cursor: pointer; + background-color: #4CAF50; + color: white; + border: none; + border-radius: 5px; +} + +#greetings { + font-size: 32px; + text-align: center; + margin-top: 20px; +} + +#fireworksCanvas { + background: transparent; + position: absolute; + top: 0; + left: 0; + width: 100%; + height: 100%; + z-index: 1; + pointer-events: none; /* 允许鼠标事件穿透canvas */ +}