126 lines
5.0 KiB
JavaScript
126 lines
5.0 KiB
JavaScript
(function(){
|
|
// 初始化函数 用于启动雪花效果
|
|
function init(){
|
|
const canvas = document.getElementById('effectiveAppsSnow');
|
|
// 条件判断 如果未找到画布元素则不执行
|
|
if (!canvas) return;
|
|
const context = canvas.getContext('2d');
|
|
let viewportWidth = window.innerWidth;
|
|
let viewportHeight = window.innerHeight;
|
|
const devicePixelRatio = window.devicePixelRatio || 1;
|
|
|
|
// 读取选中的形状集合 简化为仅使用复选框集合
|
|
const selectedShapes = (window.YooneSnowSettings && Array.isArray(window.YooneSnowSettings.selectedShapes) && window.YooneSnowSettings.selectedShapes.length > 0)
|
|
? window.YooneSnowSettings.selectedShapes
|
|
: ['dot','flake'];
|
|
// 读取媒体形状列表 用于将媒体图片作为形状参与渲染
|
|
const mediaItems = (window.YooneSnowSettings && Array.isArray(window.YooneSnowSettings.mediaItems))
|
|
? window.YooneSnowSettings.mediaItems
|
|
: [];
|
|
|
|
function resizeCanvas(){
|
|
viewportWidth = window.innerWidth;
|
|
viewportHeight = window.innerHeight;
|
|
const displayWidth = viewportWidth;
|
|
const 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();
|
|
|
|
const snowflakeCount = Math.floor(Math.min(400, Math.max(120, (viewportWidth * viewportHeight) / 12000)));
|
|
const snowflakes = [];
|
|
for (let i = 0; i < snowflakeCount; i++){
|
|
// 为每个雪花确定形状类型 从选中集合与媒体列表的合并池中随机选择
|
|
const poolSize = selectedShapes.length + mediaItems.length;
|
|
const randomIndex = Math.floor(Math.random() * Math.max(1, poolSize));
|
|
let chosenType = 'dot';
|
|
let chosenImageUrl = null;
|
|
if (randomIndex < selectedShapes.length) {
|
|
// 条件判断 使用普通形状类型
|
|
chosenType = selectedShapes[randomIndex];
|
|
} else if (mediaItems.length > 0) {
|
|
// 条件判断 使用媒体图片作为形状 并记录其 URL
|
|
const mediaIndex = randomIndex - selectedShapes.length;
|
|
chosenType = 'media_image';
|
|
chosenImageUrl = mediaItems[mediaIndex % mediaItems.length];
|
|
}
|
|
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: chosenType,
|
|
imageUrl: chosenImageUrl
|
|
});
|
|
}
|
|
|
|
function updateSnowflakes(){
|
|
for (let j = 0; j < snowflakes.length; j++){
|
|
const 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 drawSnowflakes(){
|
|
context.clearRect(0, 0, viewportWidth, viewportHeight);
|
|
|
|
for (let k = 0; k < snowflakes.length; k++){
|
|
const flake = snowflakes[k];
|
|
// 条件判断 如果是媒体图片类型则使用通用图像渲染
|
|
if (flake.shapeType === 'media_image' && flake.imageUrl){
|
|
const record = window.YooneSnowGetOrLoadImage ? window.YooneSnowGetOrLoadImage(flake.imageUrl) : { img: null, ready: false };
|
|
if (record && record.ready){
|
|
const targetHeight = flake.radius * 8;
|
|
const targetWidth = targetHeight;
|
|
window.YooneSnowDrawCenteredImage(context, record.img, flake.positionX, flake.positionY, targetWidth, targetHeight);
|
|
}
|
|
continue;
|
|
}
|
|
// 否则执行注册表中的形状渲染函数
|
|
const registry = window.YooneSnowShapeRenderers || {};
|
|
const renderer = registry[flake.shapeType] || registry['dot'];
|
|
if (typeof renderer === 'function'){
|
|
renderer(context, flake.positionX, flake.positionY, flake.radius);
|
|
}
|
|
}
|
|
}
|
|
|
|
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();
|
|
}
|
|
})();
|