秋天落叶可视化
1. 视觉效果
(一)柔和的秋季配色方案:使用了米色渐变背景,搭配黄色、橙色和深橙色的落叶,营造温暖秋日氛围
(二)逼真的落叶物理效果:每片叶子都有独特的旋转、摆动和下落轨迹
(三)深度感和细节:
①落叶使用径向渐变填充,增强立体感
②添加了高光效果,模拟光线照射
③绘制了叶脉纹理,增加真实感
④背景添加了太阳和云朵元素,增强场景感
2. 交互功能
(一)鼠标交互:移动鼠标可以产生微风,影响落叶飘动方向
(二)控制面板:
①落叶数量:调整屏幕上落叶的密度
②风力强度:控制风的大小和方向
③下落速度:调整落叶飘落的速度
3. 技术实现
(一)Canvas绘图:使用HTML5 Canvas实现高性能的动画效果
(二)面向对象设计:每个落叶都是独立的对象,有自己的属性和行为
(三)物理模拟:
①重力效果:叶子持续向下飘落
②风力效果:叶子水平方向摆动
③旋转效果:叶子在飘落过程中旋转
④贝塞尔曲线:用于绘制自然的叶子形状
4. 响应式设计
页面自动适应不同屏幕尺寸
在移动设备上优化控制面板布局
5.截图展示
6.代码重现
<!DOCTYPE html>
<html lang="zh-CN">
<head><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>秋日落叶 | 视觉盛宴</title><link href="https://fonts.googleapis.com/css2?family=Ma+Shan+Zheng&display=swap" rel="stylesheet"><style>* {margin: 0;padding: 0;box-sizing: border-box;}body {font-family: 'Ma Shan Zheng', cursive, sans-serif;background: linear-gradient(to bottom, #FFF8E7, #FFEED8);min-height: 100vh;overflow: hidden;position: relative;color: #5D4037;}/* 装饰性背景元素 */.background-elements {position: absolute;top: 0;left: 0;width: 100%;height: 100%;z-index: 1;pointer-events: none;}.sun {position: absolute;top: 10%;right: 15%;width: 120px;height: 120px;background: radial-gradient(circle, #FFE57F 30%, transparent 70%);border-radius: 50%;box-shadow: 0 0 60px rgba(255, 204, 128, 0.7);opacity: 0.7;}.cloud {position: absolute;background: rgba(255, 255, 255, 0.7);border-radius: 50%;box-shadow: 0 0 20px rgba(255, 255, 255, 0.5);}.cloud-1 {width: 200px;height: 60px;top: 15%;left: 5%;}.cloud-2 {width: 180px;height: 50px;top: 25%;right: 10%;}/* 标题区域 */.header {position: relative;z-index: 10;text-align: center;padding: 30px 20px 20px;max-width: 800px;margin: 0 auto;}.title {font-size: 3.5rem;color: #E65100;margin-bottom: 10px;text-shadow: 2px 2px 4px rgba(0, 0, 0, 0.1);letter-spacing: 3px;}.subtitle {font-size: 1.2rem;color: #5D4037;margin-bottom: 25px;max-width: 600px;margin-left: auto;margin-right: auto;line-height: 1.6;}/* 控制面板 */.controls {background: rgba(255, 255, 255, 0.3);backdrop-filter: blur(10px);border-radius: 20px;padding: 20px;display: inline-flex;flex-wrap: wrap;justify-content: center;gap: 15px;box-shadow: 0 8px 32px rgba(31, 38, 135, 0.1);border: 1px solid rgba(255, 255, 255, 0.4);margin-top: 15px;}.control-group {display: flex;flex-direction: column;align-items: center;}label {font-size: 0.9rem;margin-bottom: 5px;color: #5D4037;}input[type="range"] {width: 120px;cursor: pointer;}/* 画布容器 */.canvas-container {position: relative;width: 100%;height: 70vh;z-index: 5;overflow: hidden;border-top: 2px dashed rgba(139, 69, 19, 0.2);border-bottom: 2px dashed rgba(139, 69, 19, 0.2);margin-top: 10px;}#leafCanvas {position: absolute;top: 0;left: 0;width: 100%;height: 100%;}/* 底部信息 */.info {text-align: center;padding: 20px;font-size: 0.9rem;color: #5D4037;position: relative;z-index: 10;max-width: 800px;margin: 0 auto;}.tip {background: rgba(255, 255, 255, 0.4);display: inline-block;padding: 12px 25px;border-radius: 30px;margin-top: 10px;font-size: 0.95rem;box-shadow: 0 4px 15px rgba(0, 0, 0, 0.05);}/* 响应式设计 */@media (max-width: 768px) {.title {font-size: 2.5rem;}.subtitle {font-size: 1rem;}.controls {padding: 15px;}input[type="range"] {width: 100px;}}@media (max-width: 480px) {.title {font-size: 2rem;}.controls {flex-direction: column;align-items: center;}}</style>
</head>
<body><!-- 背景装饰元素 --><div class="background-elements"><div class="sun"></div><div class="cloud cloud-1"></div><div class="cloud cloud-2"></div></div><!-- 标题区域 --><div class="header"><h1 class="title">秋日落叶</h1><p class="subtitle">感受秋天的温柔气息,欣赏落叶在微风中翩翩起舞的优雅姿态</p><!-- 控制面板 --><div class="controls"><div class="control-group"><label for="leafCount">落叶数量</label><input type="range" id="leafCount" min="10" max="200" value="80"></div><div class="control-group"><label for="windStrength">风力强度</label><input type="range" id="windStrength" min="-2" max="2" step="0.1" value="0.5"></div><div class="control-group"><label for="fallSpeed">下落速度</label><input type="range" id="fallSpeed" min="0.5" max="3" step="0.1" value="1.5"></div></div></div><!-- 画布区域 --><div class="canvas-container"><canvas id="leafCanvas"></canvas></div><!-- 底部信息 --><div class="info"><p>移动鼠标可产生微风,让落叶跟随您的光标飘动</p><p class="tip">温馨提示:调整上方滑块可改变落叶效果</p></div><script>// 获取Canvas元素和上下文const canvas = document.getElementById('leafCanvas');const ctx = canvas.getContext('2d');// 设置Canvas尺寸为窗口大小function resizeCanvas() {canvas.width = window.innerWidth;canvas.height = window.innerHeight * 0.7; // 70vh}// 初始化时设置尺寸resizeCanvas();// 窗口大小改变时重新设置尺寸window.addEventListener('resize', resizeCanvas);// 落叶类class Leaf {constructor() {this.reset();// 随机选择落叶颜色const colors = ['#FFAB40', // 橙色'#FFD54F', // 黄色'#E65100', // 深橙色'#F57C00', // 南瓜色'#FFB74D' // 浅橙色];this.color = colors[Math.floor(Math.random() * colors.length)];this.size = Math.random() * 15 + 10; // 10-25px}reset() {this.x = Math.random() * canvas.width;this.y = -20;this.rotation = Math.random() * Math.PI * 2;this.rotationSpeed = (Math.random() - 0.5) * 0.1;this.speedY = Math.random() * 0.5 + 0.5;this.speedX = (Math.random() - 0.5) * 0.5;this.amplitude = Math.random() * 2 + 1;this.oscillation = Math.random() * Math.PI * 2;this.oscillationSpeed = Math.random() * 0.05 + 0.02;}update(wind, fallSpeed) {// 更新位置this.y += this.speedY * fallSpeed;this.x += this.speedX + wind + Math.sin(this.oscillation) * this.amplitude;// 更新旋转和摆动this.rotation += this.rotationSpeed;this.oscillation += this.oscillationSpeed;// 如果落叶飘出屏幕,重置它if (this.y > canvas.height + 20 || this.x < -20 || this.x > canvas.width + 20) {this.reset();}}draw() {ctx.save();ctx.translate(this.x, this.y);ctx.rotate(this.rotation);// 绘制落叶形状this.drawLeafShape();// 添加高光效果this.drawHighlight();ctx.restore();}drawLeafShape() {ctx.beginPath();// 绘制叶子形状(椭圆带尖)ctx.moveTo(0, 0);ctx.bezierCurveTo(this.size * 0.8, -this.size * 0.5,this.size * 0.6, -this.size * 0.8,0, -this.size * 1.2);ctx.bezierCurveTo(-this.size * 0.6, -this.size * 0.8,-this.size * 0.8, -this.size * 0.5,0, 0);ctx.closePath();// 填充叶子颜色const gradient = ctx.createRadialGradient(0, -this.size/3, this.size/4,0, -this.size/3, this.size);gradient.addColorStop(0, this.color);gradient.addColorStop(1, this.darkenColor(this.color, 20));ctx.fillStyle = gradient;ctx.fill();// 添加叶子纹理ctx.beginPath();ctx.moveTo(0, -this.size * 1.2);ctx.lineTo(0, 0);ctx.strokeStyle = this.darkenColor(this.color, 30);ctx.lineWidth = 1;ctx.stroke();}drawHighlight() {ctx.beginPath();ctx.ellipse(this.size * 0.3, -this.size * 0.7, this.size * 0.15, this.size * 0.3, Math.PI/4, 0, Math.PI * 2);const gradient = ctx.createRadialGradient(this.size * 0.3, -this.size * 0.7, 0,this.size * 0.3, -this.size * 0.7, this.size * 0.3);gradient.addColorStop(0, 'rgba(255, 255, 255, 0.5)');gradient.addColorStop(1, 'rgba(255, 255, 255, 0)');ctx.fillStyle = gradient;ctx.fill();}// 辅助函数:加深颜色darkenColor(color, percent) {let r = parseInt(color.substr(1, 2), 16);let g = parseInt(color.substr(3, 2), 16);let b = parseInt(color.substr(5, 2), 16);r = Math.floor(r * (100 - percent) / 100);g = Math.floor(g * (100 - percent) / 100);b = Math.floor(b * (100 - percent) / 100);return `#${r.toString(16).padStart(2, '0')}${g.toString(16).padStart(2, '0')}${b.toString(16).padStart(2, '0')}`;}}// 创建落叶数组let leaves = [];let leafCount = 80; // 初始落叶数量// 初始化落叶function initLeaves() {leaves = [];for (let i = 0; i < leafCount; i++) {leaves.push(new Leaf());// 设置随机初始位置leaves[i].y = Math.random() * canvas.height;}}// 鼠标位置(用于交互效果)let mouseX = null;let mouseY = null;// 监听鼠标移动canvas.addEventListener('mousemove', (e) => {const rect = canvas.getBoundingClientRect();mouseX = e.clientX - rect.left;mouseY = e.clientY - rect.top;});canvas.addEventListener('mouseleave', () => {mouseX = null;mouseY = null;});// 控制滑块const leafCountSlider = document.getElementById('leafCount');const windStrengthSlider = document.getElementById('windStrength');const fallSpeedSlider = document.getElementById('fallSpeed');leafCountSlider.addEventListener('input', () => {leafCount = parseInt(leafCountSlider.value);initLeaves();});// 动画循环function animate() {// 获取当前设置const wind = parseFloat(windStrengthSlider.value);const fallSpeed = parseFloat(fallSpeedSlider.value);// 清除画布,使用半透明背景实现拖尾效果ctx.fillStyle = 'rgba(255, 254, 248, 0.1)';ctx.fillRect(0, 0, canvas.width, canvas.height);// 更新并绘制所有落叶leaves.forEach(leaf => {// 鼠标交互:当鼠标靠近时增加风力效果if (mouseX !== null && mouseY !== null) {const dx = leaf.x - mouseX;const dy = leaf.y - mouseY;const distance = Math.sqrt(dx * dx + dy * dy);if (distance < 150) {// 根据距离计算风力影响const force = (1 - distance / 150) * 1.5;leaf.speedX += (dx / distance) * force * 0.1;leaf.speedY += (dy / distance) * force * 0.1;}}leaf.update(wind, fallSpeed);leaf.draw();});requestAnimationFrame(animate);}// 初始化并启动动画initLeaves();animate();</script>
</body>
</html>