<!DOCTYPE html>
<html lang="zh-CN">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>HTML5 Canvas龙卷风特效</title>
<style>
body {
margin: 0;
padding: 0;
height: 100vh;
overflow: hidden;
background: linear-gradient(to bottom, #1a1a2e 0%, #16213e 100%);
display: flex;
justify-content: center;
align-items: center;
font-family: Arial, sans-serif;
}
canvas {
display: block;
position: absolute;
top: 0;
left: 0;
}
.controls {
position: absolute;
bottom: 20px;
left: 50%;
transform: translateX(-50%);
display: flex;
gap: 10px;
z-index: 2;
}
.control-btn {
padding: 8px 15px;
background: rgba(255, 255, 255, 0.2);
color: white;
border: 1px solid rgba(255, 255, 255, 0.3);
border-radius: 20px;
cursor: pointer;
transition: all 0.3s ease;
}
.control-btn:hover {
background: rgba(255, 255, 255, 0.3);
}
.intensity-display {
color: white;
padding: 8px 15px;
background: rgba(0, 0, 0, 0.3);
border-radius: 20px;
}
.title {
position: absolute;
top: 20px;
left: 0;
width: 100%;
text-align: center;
color: white;
font-size: 2rem;
text-shadow: 0 2px 5px rgba(0, 0, 0, 0.5);
z-index: 2;
}
/* 版权信息 */
.footer {
position: absolute;
bottom: 10px;
right: 10px;
color: rgba(255, 255, 255, 0.5);
font-size: 12px;
z-index: 3;
}
.footer a {
color: #00f5d4;
text-decoration: none;
}
.footer a:hover {
text-decoration: underline;
}
</style>
</head>
<body>
<h1 class="title">HTML5 Canvas龙卷风特效</h1>
<canvas id="tornadoCanvas"></canvas>
<div class="controls">
<button class="control-btn" id="increaseBtn">增强</button>
<div class="intensity-display">强度: <span id="intensityValue">5</span></div>
<button class="control-btn" id="decreaseBtn">减弱</button>
</div>
<!-- 版权信息 -->
<div class="footer">
</div>
<script>
document.addEventListener('DOMContentLoaded', function() {
const canvas = document.getElementById('tornadoCanvas');
const ctx = canvas.getContext('2d');
const increaseBtn = document.getElementById('increaseBtn');
const decreaseBtn = document.getElementById('decreaseBtn');
const intensityValue = document.getElementById('intensityValue');
// 设置画布大小为窗口大小
function resizeCanvas() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
window.addEventListener('resize', resizeCanvas);
resizeCanvas();
// 龙卷风参数
let intensity = 5;
let particles = [];
const maxParticles = 500;
// 粒子类
class Particle {
constructor() {
this.reset();
this.y = Math.random() * canvas.height;
}
reset() {
this.x = canvas.width / 2 + (Math.random() - 0.5) * 50;
this.y = -20;
this.size = Math.random() * 3 + 1;
this.speed = Math.random() * 3 + 1 * (intensity / 5);
this.angle = 0;
this.spin = Math.random() * 0.2 - 0.1;
this.radius = Math.random() * 10 + 5;
this.color = `rgba(200, 200, 200, ${Math.random() * 0.5 + 0.1})`;
}
update() {
this.angle += this.spin;
this.x = canvas.width / 2 + Math.cos(this.angle) * this.radius * (this.y / canvas.height * 2);
this.y += this.speed;
// 增加随强度变化的水平移动
this.x += (Math.random() - 0.5) * intensity;
// 粒子大小随高度变化
this.size = (1 - this.y / canvas.height) * 3 + 1;
if (this.y > canvas.height) {
this.reset();
}
}
draw() {
ctx.beginPath();
ctx.arc(this.x, this.y, this.size, 0, Math.PI * 2);
ctx.fillStyle = this.color;
ctx.fill();
}
}
// 初始化粒子
function initParticles() {
particles = [];
for (let i = 0; i < maxParticles * (intensity / 10); i++) {
particles.push(new Particle());
}
}
initParticles();
// 绘制龙卷风底部
function drawTornadoBase() {
const gradient = ctx.createRadialGradient(
canvas.width / 2, canvas.height, 0,
canvas.width / 2, canvas.height, canvas.width / 3
);
gradient.addColorStop(0, 'rgba(100, 100, 100, 0.8)');
gradient.addColorStop(1, 'rgba(100, 100, 100, 0)');
ctx.beginPath();
ctx.ellipse(
canvas.width / 2, canvas.height,
canvas.width / 3, 50,
0, 0, Math.PI * 2
);
ctx.fillStyle = gradient;
ctx.fill();
}
// 动画循环
function animate() {
ctx.fillStyle = 'rgba(26, 26, 46, 0.2)';
ctx.fillRect(0, 0, canvas.width, canvas.height);
drawTornadoBase();
// 更新和绘制所有粒子
particles.forEach(particle => {
particle.update();
particle.draw();
});
requestAnimationFrame(animate);
}
animate();
// 控制按钮事件
increaseBtn.addEventListener('click', function() {
if (intensity < 10) {
intensity++;
intensityValue.textContent = intensity;
initParticles();
}
});
decreaseBtn.addEventListener('click', function() {
if (intensity > 1) {
intensity--;
intensityValue.textContent = intensity;
initParticles();
}
});
// 鼠标移动影响龙卷风
canvas.addEventListener('mousemove', function(e) {
const mouseX = e.clientX;
const dx = mouseX - canvas.width / 2;
// 根据鼠标位置轻微影响粒子
particles.forEach(particle => {
particle.x += dx * 0.0005 * particle.y;
});
});
});
</script>
</body>
</html>