网页樱花飘落特效
网页樱花飘落特效
给博客添加唯美的樱花飘落动画效果,浪漫且性能良好。
这是一个基于 HTML5 Canvas 实现的樱花飘落特效。可以在网页上添加飘落的樱花花瓣,支持开关控制,移动端自动禁用以优化性能。
效果演示
点击下方按钮开启/关闭樱花飘落效果:
👇 点击体验樱花飘落
完整代码
// 首先检测是否为移动设备,移动端不加载
if (! (navigator.userAgent.match(/(iPhone|iPod|Android|ios|iPad)/i))) {
var stop, staticx;
var img = new Image();
img.src = './img/huaban.png'; // 滑板图片(樱花素材)
// 樱花类
function Sakura(x, y, s, r, fn) {
this.x = x; // X 坐标
this.y = y; // Y 坐标
this.s = s; // 大小
this.r = r; // 旋转角度
this.fn = fn; // 运动函数
}
// 绘制樱花
Sakura.prototype.draw = function (cxt) {
cxt.save();
cxt.translate(this.x, this.y);
cxt.rotate(this.r);
cxt.drawImage(img, 0, 0, 40 * this.s, 40 * this.s)
cxt.restore();
}
// 更新樱花位置
Sakura.prototype.update = function () {
this.x = this.fn.x(this.x, this.y);
this.y = this.fn.y(this.y, this.y);
this.r = this.fn.r(this.r);
// 超出边界后重置
if (this.x > window.innerWidth || this.x < 0 ||
this.y > window.innerHeight || this.y < 0) {
this.r = getRandom('fnr');
if (Math.random() > 0.4) {
this.x = getRandom('x');
this.y = 0;
this.s = getRandom('s');
} else {
this.x = window.innerWidth;
this.y = getRandom('y');
this.s = getRandom('s');
}
}
}
// 樱花列表
SakuraList = function () { this.list = []; }
SakuraList.prototype.push = function (sakura) { this.list.push(sakura); }
SakuraList.prototype.update = function () {
for (var i = 0, len = this.list.length; i < len; i++) {
this.list[i].update();
}
}
SakuraList.prototype.draw = function (cxt) {
for (var i = 0, len = this.list.length; i < len; i++) {
this.list[i].draw(cxt);
}
}
// 随机参数生成器
function getRandom(option) {
var ret, random;
switch (option) {
case 'x': ret = Math.random() * window.innerWidth; break;
case 'y': ret = Math.random() * window.innerHeight; break;
case 's': ret = Math.random(); break;
case 'r': ret = Math.random() * 6; break;
case 'fnx':
random = -0.5 + Math.random() * 1;
ret = function (x, y) { return x + 0.5 * random - 1.7; };
break;
case 'fny':
random = 1.5 + Math.random() * 0.7;
ret = function (x, y) { return y + random; };
break;
case 'fnr':
random = Math.random() * 0.03;
ret = function (r) { return r + random; };
break;
}
return ret;
}
// 启动樱花特效
function startSakura() {
var canvas = document.createElement('canvas');
canvas.height = window.innerHeight;
canvas.width = window.innerWidth;
canvas.setAttribute('style', 'position: fixed;left: 0;top: 0;pointer-events: none;z-index:99999;');
canvas.setAttribute('id', 'canvas_sakura');
document.body.appendChild(canvas);
var cxt = canvas.getContext('2d');
var sakuraList = new SakuraList();
for (var i = 0; i < 50; i++) {
var sakura = new Sakura(
getRandom('x'), getRandom('y'), getRandom('s'), getRandom('r'),
{ x: getRandom('fnx'), y: getRandom('fny'), r: getRandom('fnr') }
);
sakura.draw(cxt);
sakuraList.push(sakura);
}
stop = requestAnimationFrame(function () {
cxt.clearRect(0, 0, canvas.width, canvas.height);
sakuraList.update();
sakuraList.draw(cxt);
stop = requestAnimationFrame(arguments.callee);
})
}
// 停止樱花特效
function stopp() {
if (staticx) {
var child = document.getElementById("canvas_sakura");
child.parentNode.removeChild(child);
window.cancelAnimationFrame(stop);
staticx = false;
} else {
startSakura();
}
}
img.onload = function () { startSakura(); }
}核心机制解析
1. 移动端检测
if (! (navigator.userAgent.match(/(iPhone|iPod|Android|ios|iPad)/i))) {
// 仅在非移动设备加载樱花特效
}通过 UserAgent 检测是否为移动设备,移动端自动跳过加载,节省流量并提升性能。
2. Canvas 画布创建
var canvas = document.createElement('canvas'); canvas.setAttribute('style', 'position: fixed;left: 0;top: 0;pointer-events: none;z-index:99999;');创建全屏 Canvas,使用 fixed 定位覆盖整个页面,z-index 99999 确保在最顶层,pointer-events: none 让点击穿透不影响页面交互。
3. 樱花对象与运动函数
| 属性 | 作用 |
|---|---|
| x, y | 樱花在画布上的坐标位置 |
| s | 大小缩放比例 (0-1) |
| r | 旋转角度 |
| fn.x, fn.y | 控制飘落轨迹的函数 |
| fn.r | 控制旋转变化的函数 |
4. requestAnimationFrame 动画循环
stop = requestAnimationFrame(function () {
cxt.clearRect(0, 0, canvas.width, canvas.height); // 清除画布
sakuraList.update(); // 更新所有樱花位置
sakuraList.draw(cxt); // 重新绘制
stop = requestAnimationFrame(arguments.callee); // 循环
})使用 requestAnimationFrame 实现流畅的 60fps 动画,比 setInterval 性能更好。
5. 边界检测与循环再生
if (this.x > window.innerWidth || this.y > window.innerHeight) {
// 超出边界后从顶部或右侧重新出现
this.x = getRandom('x');
this.y = 0;
}樱花落下后不会销毁,而是重置位置实现循环利用,减少内存开销。
樱花素材
需要准备一张樱花/花瓣图片,命名为 huaban.png,放在 ./img/ 目录下。也可以使用其他图片素材(如树叶、雪花等)实现不同效果。
可调节参数
| 参数 | 默认值 | 作用 |
|---|---|---|
| i < 50 | 50 | 樱花数量,可增减 |
| 40 * this.s | 40px | 樱花最大尺寸 |
| fnx random | -0.5 ~ 1 | 水平飘动幅度 |
| fny random | 1.5 ~ 2.2 | 下落速度 |
| fnr random | 0.03 | 旋转变化速度 |
评论