feat(雪花效果): 添加雪花形状配置选项并实现不同形状的渲染
添加后台设置页面允许用户选择雪花形状(圆点、雪花或混合) 将配置传递到前端脚本并实现不同形状的雪花渲染 在插件列表添加设置链接方便快速访问
This commit is contained in:
parent
a1b53eff06
commit
a95b3e2362
|
|
@ -1,12 +1,17 @@
|
||||||
(function(){
|
(function(){
|
||||||
|
// 初始化函数 用于启动雪花效果
|
||||||
function init(){
|
function init(){
|
||||||
var canvas = document.getElementById('effectiveAppsSnow');
|
var canvas = document.getElementById('effectiveAppsSnow');
|
||||||
|
// 条件判断 如果未找到画布元素则不执行
|
||||||
if (!canvas) return;
|
if (!canvas) return;
|
||||||
var context = canvas.getContext('2d');
|
var context = canvas.getContext('2d');
|
||||||
var viewportWidth = window.innerWidth;
|
var viewportWidth = window.innerWidth;
|
||||||
var viewportHeight = window.innerHeight;
|
var viewportHeight = window.innerHeight;
|
||||||
var devicePixelRatio = window.devicePixelRatio || 1;
|
var devicePixelRatio = window.devicePixelRatio || 1;
|
||||||
|
|
||||||
|
// 从后端配置读取雪花形状 默认值为 dot
|
||||||
|
var configuredShape = (window.YooneSnowSettings && window.YooneSnowSettings.shape) ? window.YooneSnowSettings.shape : 'dot';
|
||||||
|
|
||||||
function resizeCanvas(){
|
function resizeCanvas(){
|
||||||
viewportWidth = window.innerWidth;
|
viewportWidth = window.innerWidth;
|
||||||
viewportHeight = window.innerHeight;
|
viewportHeight = window.innerHeight;
|
||||||
|
|
@ -24,12 +29,21 @@
|
||||||
var snowflakeCount = Math.floor(Math.min(400, Math.max(120, (viewportWidth * viewportHeight) / 12000)));
|
var snowflakeCount = Math.floor(Math.min(400, Math.max(120, (viewportWidth * viewportHeight) / 12000)));
|
||||||
var snowflakes = [];
|
var snowflakes = [];
|
||||||
for (var i = 0; i < snowflakeCount; i++){
|
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({
|
snowflakes.push({
|
||||||
positionX: Math.random() * viewportWidth,
|
positionX: Math.random() * viewportWidth,
|
||||||
positionY: Math.random() * viewportHeight,
|
positionY: Math.random() * viewportHeight,
|
||||||
radius: Math.random() * 2 + 1,
|
radius: Math.random() * 2 + 1,
|
||||||
driftSpeed: Math.random() * 0.6 + 0.4,
|
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(){
|
function drawSnowflakes(){
|
||||||
context.clearRect(0, 0, viewportWidth, viewportHeight);
|
context.clearRect(0, 0, viewportWidth, viewportHeight);
|
||||||
context.fillStyle = 'rgba(255,255,255,0.9)';
|
|
||||||
context.beginPath();
|
|
||||||
for (var k = 0; k < snowflakes.length; k++){
|
for (var k = 0; k < snowflakes.length; k++){
|
||||||
var flake = snowflakes[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(){
|
function animate(){
|
||||||
|
|
@ -75,6 +135,7 @@
|
||||||
animate();
|
animate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// 条件判断 如果文档尚未加载则等待 DOMContentLoaded 事件
|
||||||
if (document.readyState === 'loading'){
|
if (document.readyState === 'loading'){
|
||||||
document.addEventListener('DOMContentLoaded', init);
|
document.addEventListener('DOMContentLoaded', init);
|
||||||
} else {
|
} else {
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,16 @@ function yoone_snow_enqueue_assets() {
|
||||||
$script_src = plugins_url('js/snow-canvas.js', __FILE__);
|
$script_src = plugins_url('js/snow-canvas.js', __FILE__);
|
||||||
wp_register_script($script_handle, $script_src, array(), '1.1.0', true);
|
wp_register_script($script_handle, $script_src, array(), '1.1.0', true);
|
||||||
wp_enqueue_script($script_handle);
|
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() {
|
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_body_open', 'yoone_snow_render_overlay');
|
||||||
add_action('wp_footer', 'yoone_snow_render_overlay', 100);
|
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 '<p>Configure snow appearance</p>';
|
||||||
|
},
|
||||||
|
'yoone_snow'
|
||||||
|
);
|
||||||
|
|
||||||
|
// 添加设置字段 下拉选择雪花形状
|
||||||
|
add_settings_field(
|
||||||
|
'yoone_snow_shape',
|
||||||
|
'Snow Shape',
|
||||||
|
function() {
|
||||||
|
// 渲染选择框 选项值 dot flake mixed
|
||||||
|
$current = get_option('yoone_snow_shape', 'dot');
|
||||||
|
echo '<select name="yoone_snow_shape" id="yoone_snow_shape">';
|
||||||
|
echo '<option value="dot"' . selected($current, 'dot', false) . '>Dot</option>';
|
||||||
|
echo '<option value="flake"' . selected($current, 'flake', false) . '>Snowflake</option>';
|
||||||
|
echo '<option value="mixed"' . selected($current, 'mixed', false) . '>Mixed</option>';
|
||||||
|
echo '</select>';
|
||||||
|
echo '<p class="description">Choose dot snowflake or mixed</p>';
|
||||||
|
},
|
||||||
|
'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 '<div class="wrap">';
|
||||||
|
echo '<h1>Yoone Snow</h1>';
|
||||||
|
echo '<form method="post" action="options.php">';
|
||||||
|
settings_fields('yoone_snow_options');
|
||||||
|
do_settings_sections('yoone_snow');
|
||||||
|
submit_button();
|
||||||
|
echo '</form>';
|
||||||
|
echo '</div>';
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// 在 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 = '<a href="' . esc_url($settingsUrl) . '">Settings</a>';
|
||||||
|
// 将设置链接插入到最前面 便于用户点击
|
||||||
|
array_unshift($links, $settingsLink);
|
||||||
|
return $links;
|
||||||
|
}
|
||||||
|
|
||||||
|
// 绑定到当前插件的 action links 钩子 使用 plugin_basename 计算插件标识
|
||||||
|
add_filter('plugin_action_links_' . plugin_basename(__FILE__), 'yoone_snow_plugin_action_links');
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue