简介
这是一个基于原生Web技术打造的创意交互动画,通过HTML5,Canvas和JavaScript实现了一个粒子化背景动态小人比心动画。项目将传统动画与粒子系统相结合,展现了Web前端技术的强大表现力,无需任何第三方框架即可实现流畅的视觉效果和用户交互。
介绍
该网页代码精简(<5KB),现博主已经出社会工作了便没有闲暇时间去完善该网页,如果遇到需要修改的模块可自行优化。话不多说,直接上代码。
效果图
HTML和CSS代码
首先,我们需要一个canvas元素和一个div元素;canvas用于在其中绘制烟花,这个元素会铺满整个屏幕。div用于在屏幕中显示动态GIF(此处的表情包可设置为自己喜欢的)。
<!DOCTYPE html>
<html>
<head>
<style>
body {
margin: 0;
overflow: hidden;
background: white;
}
canvas {
display: block;
}
.text-container {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
z-index: 1;
}
</style>
</head>
<body>
<div class="text-container">
<!-- 此处可插入文字 -->
<img src="img/biubiubiu.gif" ondragstart='return false;'>
</div>
<canvas id="canvas" style="z-index:1"></canvas>
<!-- JavaScript代码将在这里插入 -->
</body>
</html>
js代码
我们需要通过js为canvas定义宽度和高度,定义Heart和particle两个动态类,并通过一些定义每次的函数去控制它们。
1,Heart类
这是定义的一个心形坠落粒子类,每次进入该页面会生成30组粒子由上到下呈现坠落效果,且会重复生成。
//心形坠落粒子类
class Heart {
constructor() {
this.reset();
this.size = Math.random() * 20 + 10;
this.color = `hsl(${Math.random() * 360}, 70%, 60%)`;
}
reset() {
this.x = Math.random() * canvas.width;
this.y = -50;
this.speed = Math.random() * 2 + 1;
this.angle = Math.random() * Math.PI * 2;
}
draw() {
ctx.save();
ctx.translate(this.x, this.y);
ctx.rotate(this.angle);
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.bezierCurveTo(-10, -15, -25, -10, -5, -25);
ctx.bezierCurveTo(15, -40, 25, -10, 0, 0);
ctx.fillStyle = this.color;
ctx.fill();
ctx.restore();
}
update() {
this.y += this.speed;
this.angle += 0.02;
if (this.y > canvas.height + 50) this.reset();
}
}
const hearts = Array(30).fill().map(() => new Heart());
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
hearts.forEach(heart => {
heart.update();
heart.draw();
});
particles.forEach((particle, index) => {
particle.update();
particle.draw();
if (particle.alpha <= 0) {
particles.splice(index, 1);
}
});
requestAnimationFrame(animate);
}
2,particle类
这是定义的点击爆炸烟花粒子类,进入网页后可点击鼠标生成爆炸烟花效果。
//爆炸烟花粒子类
class Particle {
constructor(x, y) {
this.x = x;
this.y = y;
this.size = Math.random() * 5 + 2;
this.speedX = Math.random() * 6 - 3;
this.speedY = Math.random() * 6 - 3;
this.color = `hsl(${Math.random() * 60 + 330}, 70%, 60%)`;
this.alpha = 1;
}
update() {
this.x += this.speedX;
this.y += this.speedY;
this.speedY += 0.1; // 重力效果
this.alpha -= 0.02;
}
draw() {
ctx.save();
ctx.globalAlpha = this.alpha;
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.fill();
ctx.restore();
}
}
function createParticles(x, y) {
for (let i = 0; i < 20; i++) {
particles.push(new Particle(x, y));
}
}
animate();
canvas.addEventListener('click', (e) => {
createParticles(e.clientX, e.clientY);
hearts.forEach(heart => {
const dx = e.clientX - heart.x;
const dy = e.clientY - heart.y;
const dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 100) {
heart.x += dx * 0.02;
heart.y += dy * 0.02;
}
});
});
项目完整代码
<!DOCTYPE html>
<html>
<head>
<style>
body {
margin: 0;
overflow: hidden;
background: white;
}
canvas {
display: block;
}
.text-container {
position: fixed;
top: 50%;
left: 50%;
transform: translate(-50%, -50%);
text-align: center;
z-index: 1;
}
</style>
</head>
<body>
<div class="text-container">
<!-- 此处可插入文字 -->
<img src="img/biubiubiu.gif" ondragstart='return false;'>
</div>
<canvas id="canvas" style="z-index:1"></canvas>
<script>
var canvas = document.getElementById('canvas');
var ctx = canvas.getContext('2d');
var particles = [];
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
resizeCanvas();
window.addEventListener('resize', resizeCanvas);
class Heart {
constructor() {
this.reset();
this.size = Math.random() * 20 + 10;
this.color = `hsl(${Math.random() * 360}, 70%, 60%)`;
}
reset() {
this.x = Math.random() * canvas.width;
this.y = -50;
this.speed = Math.random() * 2 + 1;
this.angle = Math.random() * Math.PI * 2;
}
draw() {
ctx.save();
ctx.translate(this.x, this.y);
ctx.rotate(this.angle);
ctx.beginPath();
ctx.moveTo(0, 0);
ctx.bezierCurveTo(-10, -15, -25, -10, -5, -25);
ctx.bezierCurveTo(15, -40, 25, -10, 0, 0);
ctx.fillStyle = this.color;
ctx.fill();
ctx.restore();
}
update() {
this.y += this.speed;
this.angle += 0.02;
if (this.y > canvas.height + 50) this.reset();
}
}
var hearts = Array(30).fill().map(() => new Heart());
function animate() {
ctx.clearRect(0, 0, canvas.width, canvas.height);
hearts.forEach(heart => {
heart.update();
heart.draw();
});
particles.forEach((particle, index) => {
particle.update();
particle.draw();
if (particle.alpha <= 0) {
particles.splice(index, 1);
}
});
requestAnimationFrame(animate);
}
class Particle {
constructor(x, y) {
this.x = x;
this.y = y;
this.size = Math.random() * 5 + 2;
this.speedX = Math.random() * 6 - 3;
this.speedY = Math.random() * 6 - 3;
this.color = `hsl(${Math.random() * 60 + 330}, 70%, 60%)`;
this.alpha = 1;
}
update() {
this.x += this.speedX;
this.y += this.speedY;
this.speedY += 0.1; // 重力效果
this.alpha -= 0.02;
}
draw() {
ctx.save();
ctx.globalAlpha = this.alpha;
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.fill();
ctx.restore();
}
}
function createParticles(x, y) {
for (let i = 0; i < 20; i++) {
particles.push(new Particle(x, y));
}
}
animate();
canvas.addEventListener('click', (e) => {
createParticles(e.clientX, e.clientY);
hearts.forEach(heart => {
var dx = e.clientX - heart.x;
var dy = e.clientY - heart.y;
var dist = Math.sqrt(dx * dx + dy * dy);
if (dist < 100) {
heart.x += dx * 0.02;
heart.y += dy * 0.02;
}
});
});
</script>
</body>
</html>
总结
通过使用HTML5,Canvas和JavaScript,我们成功地创建了一个粒子动态小人比心网页。你可以根据自己的喜好调整粒子数量、速度和颜色等参数,创造出更多样化的效果。本文到此已结束,谢谢观看!