From a95b3e236275f2e57aaadddc18c63b1d22ba53c2 Mon Sep 17 00:00:00 2001 From: tikkhun Date: Wed, 10 Dec 2025 17:51:37 +0800 Subject: [PATCH] =?UTF-8?q?feat(=E9=9B=AA=E8=8A=B1=E6=95=88=E6=9E=9C):=20?= =?UTF-8?q?=E6=B7=BB=E5=8A=A0=E9=9B=AA=E8=8A=B1=E5=BD=A2=E7=8A=B6=E9=85=8D?= =?UTF-8?q?=E7=BD=AE=E9=80=89=E9=A1=B9=E5=B9=B6=E5=AE=9E=E7=8E=B0=E4=B8=8D?= =?UTF-8?q?=E5=90=8C=E5=BD=A2=E7=8A=B6=E7=9A=84=E6=B8=B2=E6=9F=93?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 添加后台设置页面允许用户选择雪花形状(圆点、雪花或混合) 将配置传递到前端脚本并实现不同形状的雪花渲染 在插件列表添加设置链接方便快速访问 --- js/snow-canvas.js | 73 +++++++++++++++++++++++++++++++++---- yoone-snow.php | 91 +++++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 158 insertions(+), 6 deletions(-) diff --git a/js/snow-canvas.js b/js/snow-canvas.js index 4bd8fd8..58dc484 100644 --- a/js/snow-canvas.js +++ b/js/snow-canvas.js @@ -1,12 +1,17 @@ (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; @@ -24,12 +29,21 @@ 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 + swingAmplitude: Math.random() * 0.8 + 0.2, + shapeType: snowflakeShapeType }); } @@ -48,16 +62,62 @@ } } + // 绘制雪花形状 使用线段绘制六角雪花 + 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); - context.fillStyle = 'rgba(255,255,255,0.9)'; - context.beginPath(); + for (var k = 0; k < snowflakes.length; k++){ var flake = snowflakes[k]; - context.moveTo(flake.positionX, flake.positionY); - context.arc(flake.positionX, flake.positionY, flake.radius, 0, Math.PI * 2); + // 条件判断 根据形状类型绘制雪花 + if (flake.shapeType === 'dot') { + drawDot(flake.positionX, flake.positionY, flake.radius); + } else { + drawSnowflake(flake.positionX, flake.positionY, flake.radius * 3); + } } - context.fill(); } function animate(){ @@ -75,6 +135,7 @@ animate(); } + // 条件判断 如果文档尚未加载则等待 DOMContentLoaded 事件 if (document.readyState === 'loading'){ document.addEventListener('DOMContentLoaded', init); } else { diff --git a/yoone-snow.php b/yoone-snow.php index 27883f1..61d353a 100644 --- a/yoone-snow.php +++ b/yoone-snow.php @@ -23,6 +23,16 @@ function yoone_snow_enqueue_assets() { $script_src = plugins_url('js/snow-canvas.js', __FILE__); wp_register_script($script_handle, $script_src, array(), '1.1.0', true); wp_enqueue_script($script_handle); + + // 将后端设置传递到前端脚本 变量名称为 YooneSnowSettings + $shape = get_option('yoone_snow_shape', 'dot'); + if (!in_array($shape, array('dot', 'flake', 'mixed'), true)) { + // 如果选项值不合法则回退到默认值 dot + $shape = 'dot'; + } + wp_localize_script($script_handle, 'YooneSnowSettings', array( + 'shape' => $shape, + )); } function yoone_snow_render_overlay() { @@ -37,3 +47,84 @@ add_action('wp_enqueue_scripts', 'yoone_snow_enqueue_assets'); add_action('wp_body_open', 'yoone_snow_render_overlay'); add_action('wp_footer', 'yoone_snow_render_overlay', 100); +// 注册设置页面和设置项 用于选择雪花形状 +function yoone_snow_register_settings() { + // 注册设置项 选项名称为 yoone_snow_shape 默认值为 dot + register_setting('yoone_snow_options', 'yoone_snow_shape', array( + 'type' => 'string', + 'sanitize_callback' => function($value) { + // 对提交的值进行校验 只允许 dot flake mixed 三种 + $allowed = array('dot', 'flake', 'mixed'); + if (!is_string($value)) { return 'dot'; } + return in_array($value, $allowed, true) ? $value : 'dot'; + }, + 'default' => 'dot', + )); + + // 添加设置分区 标题为 Snow Settings + add_settings_section( + 'yoone_snow_section', + 'Snow Settings', + function() { + // 输出分区描述 使用英文标点保证兼容 + echo '

Configure snow appearance

'; + }, + 'yoone_snow' + ); + + // 添加设置字段 下拉选择雪花形状 + add_settings_field( + 'yoone_snow_shape', + 'Snow Shape', + function() { + // 渲染选择框 选项值 dot flake mixed + $current = get_option('yoone_snow_shape', 'dot'); + echo ''; + echo '

Choose dot snowflake or mixed

'; + }, + 'yoone_snow', + 'yoone_snow_section' + ); +} + +// 添加设置页面到后台菜单 条目在设置菜单下 +function yoone_snow_add_settings_page() { + add_options_page( + 'Yoone Snow', + 'Yoone Snow', + 'manage_options', + 'yoone_snow', + function() { + // 渲染设置页面 表单提交到 options.php + echo '
'; + echo '

Yoone Snow

'; + echo '
'; + settings_fields('yoone_snow_options'); + do_settings_sections('yoone_snow'); + submit_button(); + echo '
'; + echo '
'; + } + ); +} + +// 在 admin 初始化时注册设置 在 admin 菜单挂载页面 +add_action('admin_init', 'yoone_snow_register_settings'); +add_action('admin_menu', 'yoone_snow_add_settings_page'); + +// 在插件列表行添加 Settings 链接 指向设置页面 +function yoone_snow_plugin_action_links($links) { + // 构造设置页面链接 使用 admin_url 保证后台路径正确 + $settingsUrl = admin_url('options-general.php?page=yoone_snow'); + $settingsLink = 'Settings'; + // 将设置链接插入到最前面 便于用户点击 + array_unshift($links, $settingsLink); + return $links; +} + +// 绑定到当前插件的 action links 钩子 使用 plugin_basename 计算插件标识 +add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'yoone_snow_plugin_action_links');