145 lines
4.8 KiB
JavaScript
145 lines
4.8 KiB
JavaScript
(function(){
|
|
// 初始化函数 用于启动雪花效果
|
|
function init(){
|
|
var canvas = document.getElementById('effectiveAppsSnow');
|
|
// 条件判断 如果未找到画布元素则不执行
|
|
if (!canvas) return;
|
|
var context = canvas.getContext('2d');
|
|
var viewportWidth = window.innerWidth;
|
|
var viewportHeight = window.innerHeight;
|
|
var devicePixelRatio = window.devicePixelRatio || 1;
|
|
|
|
// 从后端配置读取雪花形状 默认值为 dot
|
|
var configuredShape = (window.YooneSnowSettings && window.YooneSnowSettings.shape) ? window.YooneSnowSettings.shape : 'dot';
|
|
|
|
function resizeCanvas(){
|
|
viewportWidth = window.innerWidth;
|
|
viewportHeight = window.innerHeight;
|
|
var displayWidth = viewportWidth;
|
|
var displayHeight = viewportHeight;
|
|
canvas.style.width = displayWidth + 'px';
|
|
canvas.style.height = displayHeight + 'px';
|
|
canvas.width = Math.floor(displayWidth * devicePixelRatio);
|
|
canvas.height = Math.floor(displayHeight * devicePixelRatio);
|
|
context.setTransform(devicePixelRatio, 0, 0, devicePixelRatio, 0, 0);
|
|
}
|
|
|
|
resizeCanvas();
|
|
|
|
var snowflakeCount = Math.floor(Math.min(400, Math.max(120, (viewportWidth * viewportHeight) / 12000)));
|
|
var snowflakes = [];
|
|
for (var i = 0; i < snowflakeCount; i++){
|
|
// 为每个雪花确定形状类型 如果是 mixed 则随机赋值 dot 或 flake
|
|
var snowflakeShapeType;
|
|
if (configuredShape === 'mixed') {
|
|
// 条件判断 随机选择雪花形状
|
|
snowflakeShapeType = Math.random() < 0.5 ? 'dot' : 'flake';
|
|
} else {
|
|
snowflakeShapeType = configuredShape;
|
|
}
|
|
snowflakes.push({
|
|
positionX: Math.random() * viewportWidth,
|
|
positionY: Math.random() * viewportHeight,
|
|
radius: Math.random() * 2 + 1,
|
|
driftSpeed: Math.random() * 0.6 + 0.4,
|
|
swingAmplitude: Math.random() * 0.8 + 0.2,
|
|
shapeType: snowflakeShapeType
|
|
});
|
|
}
|
|
|
|
function updateSnowflakes(){
|
|
for (var j = 0; j < snowflakes.length; j++){
|
|
var flake = snowflakes[j];
|
|
flake.positionY += flake.driftSpeed * 2 + flake.radius * 0.25;
|
|
flake.positionX += Math.sin(flake.positionY * 0.01) * flake.swingAmplitude;
|
|
if (flake.positionY > viewportHeight + 5){
|
|
flake.positionY = -5;
|
|
flake.positionX = Math.random() * viewportWidth;
|
|
flake.radius = Math.random() * 2 + 1;
|
|
flake.driftSpeed = Math.random() * 0.6 + 0.4;
|
|
flake.swingAmplitude = Math.random() * 0.8 + 0.2;
|
|
}
|
|
}
|
|
}
|
|
|
|
// 绘制雪花形状 使用线段绘制六角雪花
|
|
function drawSnowflake(x, y, size) {
|
|
context.save();
|
|
context.translate(x, y);
|
|
context.fillStyle = 'rgba(255,255,255,0.9)';
|
|
context.strokeStyle = 'rgba(255,255,255,0.9)';
|
|
context.lineWidth = size * 0.15;
|
|
|
|
// 循环绘制六个分支
|
|
for (var i = 0; i < 6; i++) {
|
|
context.rotate(Math.PI / 3);
|
|
context.beginPath();
|
|
context.moveTo(0, 0);
|
|
context.lineTo(0, size);
|
|
context.stroke();
|
|
|
|
// 绘制分支上的小分叉
|
|
context.beginPath();
|
|
context.moveTo(0, size * 0.3);
|
|
context.lineTo(size * 0.3, size * 0.5);
|
|
context.stroke();
|
|
|
|
context.beginPath();
|
|
context.moveTo(0, size * 0.5);
|
|
context.lineTo(-size * 0.3, size * 0.7);
|
|
context.stroke();
|
|
|
|
context.beginPath();
|
|
context.moveTo(0, size * 0.7);
|
|
context.lineTo(size * 0.3, size * 0.9);
|
|
context.stroke();
|
|
}
|
|
|
|
context.restore();
|
|
}
|
|
|
|
// 绘制圆点形状 使用填充圆形作为雪花
|
|
function drawDot(x, y, size) {
|
|
context.beginPath();
|
|
context.arc(x, y, size, 0, Math.PI * 2);
|
|
context.fillStyle = 'rgba(255,255,255,0.9)';
|
|
context.fill();
|
|
}
|
|
|
|
function drawSnowflakes(){
|
|
context.clearRect(0, 0, viewportWidth, viewportHeight);
|
|
|
|
for (var k = 0; k < snowflakes.length; k++){
|
|
var flake = snowflakes[k];
|
|
// 条件判断 根据形状类型绘制雪花
|
|
if (flake.shapeType === 'dot') {
|
|
drawDot(flake.positionX, flake.positionY, flake.radius);
|
|
} else {
|
|
drawSnowflake(flake.positionX, flake.positionY, flake.radius * 3);
|
|
}
|
|
}
|
|
}
|
|
|
|
function animate(){
|
|
updateSnowflakes();
|
|
drawSnowflakes();
|
|
requestAnimationFrame(animate);
|
|
}
|
|
|
|
window.addEventListener('resize', function(){
|
|
resizeCanvas();
|
|
viewportWidth = window.innerWidth;
|
|
viewportHeight = window.innerHeight;
|
|
});
|
|
|
|
animate();
|
|
}
|
|
|
|
// 条件判断 如果文档尚未加载则等待 DOMContentLoaded 事件
|
|
if (document.readyState === 'loading'){
|
|
document.addEventListener('DOMContentLoaded', init);
|
|
} else {
|
|
init();
|
|
}
|
|
})();
|