JS+CSS飘动季节特效
<!-- 季节特效开始 -->
<style>
#season-canvas {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 9999;
}
</style>
<script type="text/javascript">
document.addEventListener('DOMContentLoaded', function() {
// 获取当前日期并确定季节
function getSeason() {
const now = new Date();
const month = now.getMonth();
if (month >= 2 && month < 5) return 'spring';
if (month >= 5 && month < 8) return 'summer';
if (month >= 8 && month < 11) return 'fall';
return 'winter';
}
// 根据季节配置项
var config = {
maxFlakes: 50,
minSize: 3,
maxSize: 8,
minSpeed: 0.5,
maxSpeed: 3,
rotationSpeed: 0.02,
opacityMin: 0.2,
opacityMax: 1.0
};
// 根据季节设置特定配置
switch (getSeason()) {
case 'spring':
config.flakeColors = ['#FFC0CB', '#FFB6C1', '#FF69B4'];
config.snowflakeChar = '🌸';
break;
case 'summer':
config.flakeColors = ['#FFD700', '#FFA500', '#FFFF00'];
config.snowflakeChar = '☀';
break;
case 'fall':
config.flakeColors = ['#FF4500', '#FF8C00', '#FF6347'];
config.snowflakeChar = '🍁';
break;
case 'winter':
config.flakeColors = ['#FFFFFF', '#F0F0F0', '#E0E0E0'];
config.snowflakeChar = '❄';
break;
}
function setupCanvas(canvas) {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
}
function SeasonalElement(canvas, context, config) {
this.x = Math.random() * canvas.width;
this.y = Math.random() * canvas.height;
this.radius = config.minSize + Math.random() * (config.maxSize - config.minSize);
this.speedX = -0.5 + Math.random();
this.speedY = config.minSpeed + Math.random() * (config.maxSpeed - config.minSpeed);
this.color = config.flakeColors[Math.floor(Math.random() * config.flakeColors.length)];
this.rotation = Math.random() * Math.PI * 2; // 修正运算符
this.opacity = config.opacityMin + Math.random() * (config.opacityMax - config.opacityMin);
this.seasonalChar = config.snowflakeChar;
this.reset = function() {
this.x = Math.random() * canvas.width;
this.y = -this.radius;
this.radius = config.minSize + Math.random() * (config.maxSize - config.minSize);
this.speedX = -0.5 + Math.random();
this.speedY = config.minSpeed + Math.random() * (config.maxSpeed - config.minSpeed);
this.color = config.flakeColors[Math.floor(Math.random() * config.flakeColors.length)];
this.rotation = Math.random() * Math.PI * 2; // 修正运算符
this.opacity = config.opacityMin + Math.random() * (config.opacityMax - config.opacityMin);
};
this.update = function() {
this.x += this.speedX;
this.y += this.speedY;
this.rotation += config.rotationSpeed;
if (this.y > canvas.height || this.x < -this.radius || this.x > canvas.width + this.radius) {
this.reset();
}
};
this.draw = function() {
context.save();
context.translate(this.x, this.y);
context.rotate(this.rotation);
context.globalAlpha = this.opacity;
context.fillStyle = this.color;
context.font = `${this.radius * 2}px Arial`; // 使用模板字符串
context.textAlign = 'center';
context.textBaseline = 'middle';
context.fillText(this.seasonalChar, 0, 0);
context.restore();
};
}
function initSeasonalEffect(canvasElement) {
var canvas = document.getElementById(canvasElement);
var context = canvas.getContext('2d');
setupCanvas(canvas);
var elements = [];
for (var i = 0; i < config.maxFlakes; i++) {
elements.push(new SeasonalElement(canvas, context, config));
}
function animate() {
context.clearRect(0, 0, canvas.width, canvas.height);
elements.forEach(function(element) {
element.update();
element.draw();
});
requestAnimationFrame(animate);
}
animate();
window.addEventListener('resize', function() {
setupCanvas(canvas);
});
}
// 创建并添加canvas元素
var canvas = document.createElement('canvas');
canvas.id = 'season-canvas';
document.body.appendChild(canvas);
initSeasonalEffect('season-canvas');
});
</script>
<!-- 季节特效结束 -->
<!-- 优化版季节特效 -->
<style>
#season-canvas {
position: fixed;
top: 0;
left: 0;
width: 100%;
height: 100%;
pointer-events: none;
z-index: 9999;
/* 启用GPU加速 */
transform: translateZ(0);
}
</style>
<script type="text/javascript">
(function() {
// 防抖函数优化窗口resize事件[7](@ref)
function debounce(func, wait = 250) {
let timeout;
return (...args) => {
clearTimeout(timeout);
timeout = setTimeout(() => func.apply(this, args), wait);
};
}
// 离屏Canvas预渲染
class SeasonalCache {
constructor(char, color, maxSize) {
this.canvas = document.createElement('canvas');
this.ctx = this.canvas.getContext('2d');
this.generateCache(char, color, maxSize);
}
generateCache(char, color, maxSize) {
const size = maxSize * 2;
this.canvas.width = this.canvas.height = size;
this.ctx.textAlign = 'center';
this.ctx.textBaseline = 'middle';
this.ctx.font = `${maxSize}px Arial`;
this.ctx.fillStyle = color;
this.ctx.globalAlpha = 0.8;
this.ctx.fillText(char, size/2, size/2);
}
}
document.addEventListener('DOMContentLoaded', function() {
// 获取当前季节(优化计算逻辑)
const getSeason = () => ['spring','summer','fall','winter'][Math.floor((new Date().getMonth())/3)];
// 配置参数(合并重复计算)
const config = {
//粒子数量
maxFlakes: 50, // 减少粒子数量
minSize: 12,
maxSize: 24,
minSpeed: 0.8,
maxSpeed: 2.5,
rotationSpeed: 0.03,
cacheMap: new Map() // 缓存预渲染图像
};
// 季节特定配置
const seasonConfig = {
spring: { colors: ['#FFC0CB','#FFB6C1'], char: '🌸' },
summer: { colors: ['#FFD700','#FFA500'], char: '☀' },
fall: { colors: ['#FF4500','#FF8C00'], char: '🍁' },
winter: { colors: ['#FFFFFF','#F0F0F0'], char: '❄' }
}[getSeason()];
// Canvas初始化(添加设备像素比支持)
function setupCanvas(canvas) {
const dpr = window.devicePixelRatio || 1;
const rect = canvas.getBoundingClientRect();
canvas.width = rect.width * dpr;
canvas.height = rect.height * dpr;
canvas.style.width = `${rect.width}px`;
canvas.style.height = `${rect.height}px`;
canvas.getContext('2d').scale(dpr, dpr);
}
// 粒子类(优化绘制逻辑)
class SeasonalElement {
constructor(canvas, ctx) {
this.canvas = canvas;
this.ctx = ctx;
this.reset(true);
// 使用预渲染图像
if (!config.cacheMap.has(this.char)) {
config.cacheMap.set(this.char,
new SeasonalCache(this.char, this.color, this.size));
}
this.cache = config.cacheMap.get(this.char);
}
reset(init = false) {
this.char = seasonConfig.char;
this.color = seasonConfig.colors[Math.random() * 2 | 0];
this.size = config.minSize + Math.random() * (config.maxSize - config.minSize);
this.x = Math.random() * this.canvas.width;
this.y = init ? Math.random() * this.canvas.height : -this.size;
this.speedX = Math.random() * 2 - 1;
this.speedY = config.minSpeed + Math.random() * (config.maxSpeed - config.minSpeed);
this.rotation = Math.random() * Math.PI * 2;
}
update() {
this.x += this.speedX;
this.y += this.speedY;
this.rotation += config.rotationSpeed;
if (this.y > this.canvas.height + this.size) this.reset();
}
draw() {
// 使用离屏Canvas绘制
this.ctx.save();
this.ctx.translate(this.x, this.y);
this.ctx.rotate(this.rotation);
this.ctx.drawImage(
this.cache.canvas,
-this.size/2, -this.size/2,
this.size, this.size
);
this.ctx.restore();
}
}
// 初始化特效
function initSeasonalEffect() {
const canvas = document.getElementById('season-canvas');
const ctx = canvas.getContext('2d');
setupCanvas(canvas);
// 创建粒子系统
const elements = Array.from({ length: config.maxFlakes },
() => new SeasonalElement(canvas, ctx));
// 优化动画循环
let lastTime = 0;
const animate = (timestamp) => {
const deltaTime = timestamp - lastTime;
if (deltaTime > 16) { // 限制帧率≈60fps
ctx.clearRect(0, 0, canvas.width, canvas.height);
elements.forEach(e => {
e.update();
e.draw();
});
lastTime = timestamp;
}
requestAnimationFrame(animate);
};
animate(0);
// 优化resize处理
window.addEventListener('resize', debounce(() => {
setupCanvas(canvas);
elements.forEach(e => e.reset(true));
}));
}
// 创建Canvas元素
const canvas = document.createElement('canvas');
canvas.id = 'season-canvas';
document.body.appendChild(canvas);
initSeasonalEffect();
});
})();
// 请保留版权说明
if (window.console && window.console.log) {
console.log("%c ShiDai %c https://blog.elsworld.cn:8443/ ", "color: #fff; margin: 1em 0; padding: 5px 0; background: #673ab7;", "margin: 1em 0; padding: 5px 0; background: #efefef;");
}
</script>
- 感谢你赐予我前进的力量
赞赏者名单
因为你们的支持让我意识到写文章的价值🙏
评论
匿名评论
隐私政策
你无需删除空行,直接评论以获取最佳展示效果