目录
系列文章
写在前面
马上就要到2025年喽,博主用 html 给大家准备了粉色系的跨年烟花秀,一起来看看吧~
HTML(Hypertext Markup Language)是一种标记语言,用于创建网页的结构和内容。它使用一系列标签(tag)来标记文本,以指示浏览器如何展示内容。HTML是万维网的基础技术之一,它定义了网页的结构和链接方式。
HTML的发展可以追溯到1989年,由蒂姆·伯纳斯-李(Tim Berners-Lee)创始于欧洲核子研究组织(CERN)。最初,HTML只是用于将文档链接在一起,没有表现力很强。随着互联网的发展,HTML的功能逐渐增强,可以实现各种复杂的效果。
HTML由标签构成。标签通常用尖括号表示,例如<tag>。标签可以有属性(attribute),用于指定标签的属性值。属性通常包括名称和值,以键值对的形式表示。例如,<tag attribute="value">。
HTML文档通常由头部(head)和主体(body)组成。头部包含了文档的元信息,例如标题、样式表和脚本。主体包含了文档的实际内容,例如段落、标题、图像和链接。
HTML常用的标签和功能:
1. 标题标签(<h1>到<h6>)用于定义标题的级别和重要性。
2. 段落标签(<p>)用于定义段落。
3. 链接标签(<a>)用于创建链接到其他网页或文件的超链接。
4. 图像标签(<img>)用于在网页中插入图像。
5. 列表标签(<ul>和<ol>)用于创建无序列表和有序列表。
6. 表格标签(<table>、<tr>和<td>)用于创建表格。
7. 表单标签(<form>、<input>和<button>)用于创建交互式表单。
8. 样式标签(<style>)用于定义文档的样式。
9. 脚本标签(<script>)用于在网页中嵌入JavaScript脚本。
除了这些基本功能外,HTML还支持更多的标签和功能,例如音频和视频播放、动画效果、地理定位等。此外,HTML还可以与CSS(层叠样式表)和JavaScript等技术一起使用,以实现更复杂和交互式的网页效果。
总结起来,HTML是一种用于创建网页结构和内容的标记语言。它使用标签来标记文本,并告诉浏览器如何展示内容。HTML的功能丰富多样,可以实现各种各样的网页效果。掌握HTML是学习Web开发的第一步。
完整代码
<!DOCTYPE html>
<html lang="en">
<script>
var _hmt = _hmt || [];
(function () {
var hm = document.createElement("script");
hm.src = "https://hm.baidu.com/hm.js?c923daf3182a4b0ce01878475080aadc";
var s = document.getElementsByTagName("script")[0];
s.parentNode.insertBefore(hm, s);
})();
</script>
<head>
<meta charset="UTF-8">
<title>新年快乐!</title>
</head>
<style>
body {
margin: 0;
overflow: hidden;
background: black;
}
canvas {
position: absolute;
}
</style>
<body>
<canvas></canvas>
<canvas></canvas>
<canvas></canvas>
<script>
function GetRequest() {
var url = decodeURI(location.search);
var theRequest = new Object();
if (url.indexOf("?") != -1) {
var str = url.substr(1);
strs = str.split("&");
for (var i = 0; i < strs.length; i++) {
theRequest[strs[i].split("=")[0]] = unescape(strs[i].split("=")[1]);
}
}
return theRequest;
}
class Shard {
constructor(x, y, hue) {
this.x = x;
this.y = y;
this.hue = hue;
this.lightness = 50;
this.size = 15 + Math.random() * 10;
const angle = Math.random() * 2 * Math.PI;
const blastSpeed = 1 + Math.random() * 6;
this.xSpeed = Math.cos(angle) * blastSpeed;
this.ySpeed = Math.sin(angle) * blastSpeed;
this.target = getTarget();
this.ttl = 100;
this.timer = 0;
}
draw() {
ctx2.fillStyle = `hsl(${this.hue}, 100%, ${this.lightness}%)`;
ctx2.beginPath();
ctx2.arc(this.x, this.y, this.size, 0, 2 * Math.PI);
ctx2.closePath();
ctx2.fill();
}
update() {
if (this.target) {
const dx = this.target.x - this.x;
const dy = this.target.y - this.y;
const dist = Math.sqrt(dx * dx + dy * dy);
const a = Math.atan2(dy, dx);
const tx = Math.cos(a) * 5;
const ty = Math.sin(a) * 5;
this.size = lerp(this.size, 1.5, 0.05);
if (dist < 5) {
this.lightness = lerp(this.lightness, 100, 0.01);
this.xSpeed = this.ySpeed = 0;
this.x = lerp(this.x, this.target.x + fidelity / 2, 0.05);
this.y = lerp(this.y, this.target.y + fidelity / 2, 0.05);
this.timer += 1;
} else
if (dist < 10) {
this.lightness = lerp(this.lightness, 100, 0.01);
this.xSpeed = lerp(this.xSpeed, tx, 0.1);
this.ySpeed = lerp(this.ySpeed, ty, 0.1);
this.timer += 1;
} else {
this.xSpeed = lerp(this.xSpeed, tx, 0.02);
this.ySpeed = lerp(this.ySpeed, ty, 0.02);
}
} else {
this.ySpeed += 0.05;
this.size = lerp(this.size, 1, 0.05);
if (this.y > c2.height) {
shards.forEach((shard, idx) => {
if (shard === this) {
shards.splice(idx, 1);
}
});
}
}
this.x = this.x + this.xSpeed;
this.y = this.y + this.ySpeed;
}
}
class Rocket {
constructor() {
const quarterW = c2.width / 4;
this.x = quarterW + Math.random() * (c2.width - quarterW);
this.y = c2.height - 15;
this.angle = Math.random() * Math.PI / 4 - Math.PI / 6;
this.blastSpeed = 6 + Math.random() * 7;
this.shardCount = 15 + Math.floor(Math.random() * 15);
this.xSpeed = Math.sin(this.angle) * this.blastSpeed;
this.ySpeed = -Math.cos(this.angle) * this.blastSpeed;
this.hue = Math.floor(Math.random() * 360);
this.trail = [];
}
draw() {
ctx2.save();
ctx2.translate(this.x, this.y);
ctx2.rotate(Math.atan2(this.ySpeed, this.xSpeed) + Math.PI / 2);
ctx2.fillStyle = `hsl(${this.hue}, 100%, 50%)`;
ctx2.fillRect(0, 0, 5, 15);
ctx2.restore();
}
update() {
this.x = this.x + this.xSpeed;
this.y = this.y + this.ySpeed;
this.ySpeed += 0.1;
}
explode() {
for (let i = 0; i < 70; i++) {
shards.push(new Shard(this.x, this.y, this.hue));
}
}
}
console.log(GetRequest('val').val)
const [c1, c2, c3] = document.querySelectorAll('canvas');
const [ctx1, ctx2, ctx3] = [c1, c2, c3].map(c => c.getContext('2d'));
let fontSize = 200;
const rockets = [];
const shards = [];
const targets = [];
const fidelity = 3;
let counter = 0;
c2.width = c3.width = window.innerWidth;
c2.height = c3.height = window.innerHeight;
ctx1.fillStyle = 'skyblue';
const text = '新年快乐'
let textWidth = 9999;
while (textWidth > window.innerWidth) {
ctx1.font = `900 ${fontSize--}px Arial`;
textWidth = ctx1.measureText(text).width;
}
c1.width = textWidth;
c1.height = fontSize * 1.5;
ctx1.font = `900 ${fontSize}px Arial`;
ctx1.fillText(text, 0, fontSize - 30);
const imgData = ctx1.getImageData(0, 0, c1.width, c1.height);
for (let i = 0, max = imgData.data.length; i < max; i += 4) {
const alpha = imgData.data[i + 3];
const x = Math.floor(i / 4) % imgData.width;
const y = Math.floor(i / 4 / imgData.width);
if (alpha && x % fidelity === 0 && y % fidelity === 0) {
targets.push({ x, y });
}
}
ctx3.fillStyle = 'pink';
ctx3.shadowColor = 'pink';
ctx3.shadowBlur = 25;
(function loop() {
ctx2.fillStyle = "deeppink";
ctx2.fillRect(0, 0, c2.width, c2.height);
counter += 1;
if (counter % 15 === 0) {
rockets.push(new Rocket());
}
rockets.forEach((r, i) => {
r.draw();
r.update();
if (r.ySpeed > 0) {
r.explode();
rockets.splice(i, 1);
}
});
shards.forEach((s, i) => {
s.draw();
s.update();
if (s.timer >= s.ttl || s.lightness >= 99) {
ctx3.fillRect(s.target.x, s.target.y, fidelity + 1, fidelity + 1);
shards.splice(i, 1);
}
});
requestAnimationFrame(loop);
})();
const lerp = (a, b, t) => Math.abs(b - a) > 0.1 ? a + t * (b - a) : b;
function getTarget() {
if (targets.length > 0) {
const idx = Math.floor(Math.random() * targets.length);
let { x, y } = targets[idx];
targets.splice(idx, 1);
x += c2.width / 2 - textWidth / 2;
y += c2.height / 2 - fontSize / 2;
return { x, y };
}
}
</script>
</body>
</html>
修改文字
在代码的第185、186可以修改中间的文字颜色哦~
在代码的第191行可以修改背景颜色哦~
代码分析
这段代码通过HTML和JavaScript结合,创建了一个“新年快乐”主题的烟花动画,并在屏幕上显示文字“新年快乐”。其实现方式主要涉及画布(canvas)操作、火箭发射、烟花爆炸以及文字的动态生成与展示。以下是这段代码的详细分析。
一、代码结构概览
代码主要分为三部分:
- HTML结构:通过
<canvas>
标签创建三个画布,用于不同的绘图操作。 - CSS样式:设置画布和页面的样式,使背景为黑色,并使画布覆盖整个页面。
- JavaScript逻辑:核心部分,负责烟花的发射、爆炸效果以及文字的生成。
二、画布的初始化与配置
在代码中,使用了三个canvas
元素,它们通过JavaScript分别绑定到三个上下文对象:ctx1
、ctx2
和ctx3
,用于不同的绘制操作。
ctx1
:负责绘制“新年快乐”文字。ctx2
:负责绘制火箭的飞行和烟花的爆炸效果。ctx3
:用于绘制烟花爆炸后的残留效果。
这三个画布通过设置宽度和高度,确保其覆盖整个窗口。c1
的宽高根据文字的宽度和字体大小动态调整,以确保文字能够适应屏幕。
三、文字的生成
代码通过ctx1.fillText
方法在画布上绘制“新年快乐”文字。首先,代码根据屏幕的宽度动态调整字体大小,确保文字不会超出屏幕宽度。然后,getImageData
方法获取画布上的像素数据,以提取出文字的形状。
通过逐个检查像素的透明度值(alpha
),代码识别出文字中每个可见部分的坐标。接着,这些坐标存储在targets
数组中,作为烟花爆炸的目标点。烟花爆炸后,碎片会逐渐飞向这些目标点,最终在屏幕上组成文字“新年快乐”。
四、烟花动画
烟花动画的核心是Rocket
(火箭)和Shard
(烟花碎片)两个类。
- Rocket类:代表烟花的发射过程。每个火箭有随机的初始位置和发射角度,沿着一条随机的轨迹上升。
update
方法用于更新火箭的位置,模拟火箭上升的运动;当火箭达到一定高度后,通过explode
方法使其爆炸,生成多个Shard
对象。 - Shard类:代表烟花爆炸后的碎片。每个碎片有随机的速度和方向,在空中飞行并逐渐减速。碎片的目标是之前生成的文字的像素点,它们会逐渐朝着这些目标移动,直到到达目标点后停止。
在代码中,使用了requestAnimationFrame
实现动画的平滑更新。loop
函数是动画的主循环,在每一帧中都会更新火箭和碎片的位置,并重绘整个画布。
五、颜色和效果
在这段代码中,颜色的变化通过HSL色彩模型实现。每个火箭和烟花碎片都有一个随机的hue
值,决定了它们的颜色。Shard
类的draw
方法使用ctx2.arc
画圆的方法绘制每个碎片,并通过调整lightness
值模拟烟花的逐渐消失效果。
此外,代码还通过shadowColor
和shadowBlur
为爆炸后的烟花添加了阴影效果,使得爆炸显得更加闪亮逼真。
六、目标点与插值
碎片飞向文字目标点的过程使用了线性插值(lerp
)算法,lerp
函数用于在当前碎片位置与目标位置之间进行平滑过渡。通过不断缩小位置差距,碎片能够逐渐接近并最终停留在目标点。
七、火箭与碎片的生命周期
每个火箭和碎片都有各自的生命周期。当火箭上升到一定高度时,会自动触发爆炸,生成碎片。而每个碎片则在到达目标点或超过一定的存活时间后从数组中移除。这样可以避免画布上元素的无限增长,保证动画的性能和流畅度。
八、总结
这段代码通过使用HTML5的canvas
元素,结合JavaScript中的对象和动画操作,实现了一个复杂而又美观的烟花动画。代码的核心思想是将烟花的爆炸与文字的显示相结合,通过计算每个像素点的位置,使烟花碎片能够精确地拼成文字。同时,代码还采用了多种动画技巧,如随机生成、插值算法和帧动画,确保动画的自然流畅。
写在最后
我是一只有趣的兔子,感谢你的喜欢!