diff --git a/js/admin-media.js b/js/admin-media.js index 3dbf573..2febeb1 100644 --- a/js/admin-media.js +++ b/js/admin-media.js @@ -6,13 +6,119 @@ var listContainer = document.getElementById('yooneSnowMediaList'); if (!addButton || !listContainer) { return; } + // 形状与媒体权重容器元素 获取以便动态更新 + var weightsContainer = document.getElementById('yooneSnowWeightsContainer'); + var shapeWeightsBox = document.getElementById('yooneSnowShapeWeights'); + var mediaWeightsBox = document.getElementById('yooneSnowMediaWeights'); + + // 形状标签映射用于显示友好名称 + var shapeLabelsMap = { + dot: 'Dot', + flake: 'Snowflake', + yuanbao: 'Yuanbao', + coin: 'Coin', + santa_hat: 'Santa Hat', + candy_cane: 'Candy Cane', + christmas_sock: 'Christmas Sock', + christmas_tree: 'Christmas Tree', + reindeer: 'Reindeer', + christmas_berry: 'Christmas Berry' + }; + + // 同步形状权重输入 根据勾选状态增删对应输入 + function ensureShapeWeightInputs(){ + // 条件判断 权重容器不存在则跳过 + if (!shapeWeightsBox) { return; } + var checkboxes = document.querySelectorAll('input[name="yoone_snow_mixed_items[]"]'); + var presentKeys = {}; + // 收集已存在的标签记录用于对比 + var existingLabels = shapeWeightsBox.querySelectorAll('label[data-shape-key]'); + existingLabels.forEach(function(el){ + presentKeys[el.getAttribute('data-shape-key')] = el; + }); + checkboxes.forEach(function(cb){ + var key = cb.value; + if (cb.checked){ + // 条件判断 如果不存在对应输入则创建 默认权重值为 1 + if (!presentKeys[key]){ + var lab = document.createElement('label'); + lab.setAttribute('data-shape-key', key); + lab.style.display = 'flex'; + lab.style.flexDirection = 'column'; + lab.style.minWidth = '160px'; + var title = document.createElement('span'); + title.textContent = shapeLabelsMap[key] || key; + var input = document.createElement('input'); + input.type = 'number'; + input.min = '0'; + input.name = 'yoone_snow_shape_weights[' + key + ']'; + input.value = '1'; + input.style.width = '120px'; + lab.appendChild(title); + lab.appendChild(input); + shapeWeightsBox.appendChild(lab); + } + } else { + // 条件判断 如果取消勾选则移除对应输入 + var exist = shapeWeightsBox.querySelector('label[data-shape-key="' + key + '"]'); + if (exist) { exist.remove(); } + } + }); + } + + // 添加媒体权重输入 根据附件 ID 创建输入 默认值为 1 + function addMediaWeightInput(attachmentId){ + if (!mediaWeightsBox) { return; } + var exist = mediaWeightsBox.querySelector('label[data-attachment-id="' + String(attachmentId) + '"]'); + if (exist) { return; } + var lab = document.createElement('label'); + lab.setAttribute('data-attachment-id', String(attachmentId)); + lab.style.display = 'flex'; + lab.style.flexDirection = 'column'; + lab.style.minWidth = '160px'; + var title = document.createElement('span'); + title.textContent = 'Media ' + String(attachmentId); + var input = document.createElement('input'); + input.type = 'number'; + input.min = '0'; + input.name = 'yoone_snow_media_weights[' + String(attachmentId) + ']'; + input.value = '1'; + input.style.width = '120px'; + lab.appendChild(title); + lab.appendChild(input); + mediaWeightsBox.appendChild(lab); + } + + // 移除媒体权重输入 根据附件 ID 删除对应输入 + function removeMediaWeightInput(attachmentId){ + if (!mediaWeightsBox) { return; } + var exist = mediaWeightsBox.querySelector('label[data-attachment-id="' + String(attachmentId) + '"]'); + if (exist) { exist.remove(); } + } + + // 初始化时同步一次形状权重输入 + ensureShapeWeightInputs(); + + // 监听形状复选框变化事件 动态刷新权重输入 + document.addEventListener('change', function(event){ + var t = event.target; + if (t && t.name === 'yoone_snow_mixed_items[]'){ + ensureShapeWeightInputs(); + } + }); + // 绑定移除按钮事件 使用事件委托处理动态元素 listContainer.addEventListener('click', function(event){ // 条件判断 如果点击的是移除按钮则执行删除 var target = event.target; if (target && target.classList.contains('yoone-snow-remove-media')){ var item = target.closest('.yoone-snow-media-item'); - if (item) { item.remove(); } + if (item) { + var aidStr = item.getAttribute('data-attachment-id'); + item.remove(); + // 同步移除对应媒体权重输入 + if (aidStr) { removeMediaWeightInput(aidStr); } + } } }); @@ -59,6 +165,8 @@ wrapper.appendChild(input); wrapper.appendChild(removeBtn); listContainer.appendChild(wrapper); + // 同步添加媒体权重输入 默认权重为 1 + addMediaWeightInput(id); }); }); frame.open(); diff --git a/js/snow-canvas.js b/js/snow-canvas.js index de73dbb..b1b35c4 100644 --- a/js/snow-canvas.js +++ b/js/snow-canvas.js @@ -18,14 +18,56 @@ // 标记是否已达到显示时长 到达后不再生成新粒子并不再重生 let hasReachedDuration = false; - // 读取选中的形状集合 简化为仅使用复选框集合 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 : []; + const defaultShapeWeights = { dot: 1, flake: 4, yuanbao: 1, coin: 1, santa_hat: 1, candy_cane: 1, christmas_sock: 1, christmas_tree: 1, reindeer: 1, christmas_berry: 1 }; + const shapeWeightsRaw = (window.YooneSnowSettings && window.YooneSnowSettings.shapeWeights && typeof window.YooneSnowSettings.shapeWeights === 'object') + ? window.YooneSnowSettings.shapeWeights + : {}; + const mediaWeightsRaw = (window.YooneSnowSettings && window.YooneSnowSettings.mediaWeights && typeof window.YooneSnowSettings.mediaWeights === 'object') + ? window.YooneSnowSettings.mediaWeights + : {}; + const shapeWeights = {}; + for (let key in defaultShapeWeights){ + const val = typeof shapeWeightsRaw[key] !== 'undefined' ? parseInt(shapeWeightsRaw[key], 10) : defaultShapeWeights[key]; + shapeWeights[key] = isNaN(val) ? defaultShapeWeights[key] : Math.max(0, val); + } + const sizeScaleRaw = (window.YooneSnowSettings && typeof window.YooneSnowSettings.sizeScale !== 'undefined') + ? parseFloat(window.YooneSnowSettings.sizeScale) + : 1.0; + const offsetScaleRaw = (window.YooneSnowSettings && typeof window.YooneSnowSettings.offsetScale !== 'undefined') + ? parseFloat(window.YooneSnowSettings.offsetScale) + : 1.0; + const sizeScale = isNaN(sizeScaleRaw) ? 1.0 : Math.max(0.1, sizeScaleRaw); + const offsetScale = isNaN(offsetScaleRaw) ? 1.0 : Math.max(0, offsetScaleRaw); + const radiusMinRaw = (window.YooneSnowSettings && typeof window.YooneSnowSettings.radiusMin !== 'undefined') + ? parseFloat(window.YooneSnowSettings.radiusMin) + : 1.0; + const radiusMaxRaw = (window.YooneSnowSettings && typeof window.YooneSnowSettings.radiusMax !== 'undefined') + ? parseFloat(window.YooneSnowSettings.radiusMax) + : 3.0; + const driftMinRaw = (window.YooneSnowSettings && typeof window.YooneSnowSettings.driftMin !== 'undefined') + ? parseFloat(window.YooneSnowSettings.driftMin) + : 0.4; + const driftMaxRaw = (window.YooneSnowSettings && typeof window.YooneSnowSettings.driftMax !== 'undefined') + ? parseFloat(window.YooneSnowSettings.driftMax) + : 1.0; + const swingMinRaw = (window.YooneSnowSettings && typeof window.YooneSnowSettings.swingMin !== 'undefined') + ? parseFloat(window.YooneSnowSettings.swingMin) + : 0.2; + const swingMaxRaw = (window.YooneSnowSettings && typeof window.YooneSnowSettings.swingMax !== 'undefined') + ? parseFloat(window.YooneSnowSettings.swingMax) + : 1.0; + const radiusMin = isNaN(radiusMinRaw) ? 1.0 : Math.max(0, radiusMinRaw); + const radiusMax = isNaN(radiusMaxRaw) ? 3.0 : Math.max(radiusMin, radiusMaxRaw); + const driftMin = isNaN(driftMinRaw) ? 0.4 : Math.max(0, driftMinRaw); + const driftMax = isNaN(driftMaxRaw) ? 1.0 : Math.max(driftMin, driftMaxRaw); + const swingMin = isNaN(swingMinRaw) ? 0.2 : Math.max(0, swingMinRaw); + const swingMax = isNaN(swingMaxRaw) ? 1.0 : Math.max(swingMin, swingMaxRaw); function resizeCanvas(){ viewportWidth = window.innerWidth; @@ -41,35 +83,64 @@ resizeCanvas(); - const snowflakeCount = Math.floor(Math.min(400, Math.max(120, (viewportWidth * viewportHeight) / 12000))); + const snowflakesTargetCount = 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]; + function selectWeightedItem(){ + const items = []; + for (let sIndex = 0; sIndex < selectedShapes.length; sIndex++){ + const shapeKey = selectedShapes[sIndex]; + const weightVal = typeof shapeWeights[shapeKey] !== 'undefined' ? shapeWeights[shapeKey] : 1; + if (weightVal > 0){ + items.push({ kind: 'shape', key: shapeKey, weight: weightVal }); + } } - snowflakes.push({ + for (let mIndex = 0; mIndex < mediaItems.length; mIndex++){ + const mediaUrl = mediaItems[mIndex]; + const mediaWeight = typeof mediaWeightsRaw[mediaUrl] !== 'undefined' ? parseInt(mediaWeightsRaw[mediaUrl], 10) : 1; + const finalMediaWeight = isNaN(mediaWeight) ? 1 : Math.max(0, mediaWeight); + if (finalMediaWeight > 0){ + items.push({ kind: 'media', url: mediaUrl, weight: finalMediaWeight }); + } + } + if (items.length === 0){ + return { type: 'dot', url: null }; + } + let totalWeight = 0; + for (let i = 0; i < items.length; i++){ + totalWeight += items[i].weight; + } + const r = Math.random() * totalWeight; + let acc = 0; + for (let i = 0; i < items.length; i++){ + acc += items[i].weight; + if (r <= acc){ + if (items[i].kind === 'shape'){ + return { type: items[i].key, url: null }; + } else { + return { type: 'media_image', url: items[i].url }; + } + } + } + return { type: 'dot', url: null }; + } + function createSnowflake(){ + const picked = selectWeightedItem(); + let chosenType = picked.type; + let chosenImageUrl = picked.url; + return { 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, + positionY: -5 - Math.random() * 20, + radius: (Math.random() * (radiusMax - radiusMin) + radiusMin) * sizeScale, + driftSpeed: Math.random() * (driftMax - driftMin) + driftMin, + swingAmplitude: (Math.random() * (swingMax - swingMin) + swingMin) * offsetScale, shapeType: chosenType, imageUrl: chosenImageUrl, // 标记该粒子是否已经移出视口 用于停止后清理 outOfView: false - }); + }; } + const spawnIntervalMs = Math.max(10, Math.floor(4000 / Math.max(1, snowflakesTargetCount))); + let nextSpawnTimestamp = performance.now(); function updateSnowflakes(){ for (let j = 0; j < snowflakes.length; j++){ @@ -81,9 +152,9 @@ if (!hasReachedDuration){ 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; + flake.radius = (Math.random() * (radiusMax - radiusMin) + radiusMin) * sizeScale; + flake.driftSpeed = Math.random() * (driftMax - driftMin) + driftMin; + flake.swingAmplitude = (Math.random() * (swingMax - swingMin) + swingMin) * offsetScale; } else { flake.outOfView = true; } @@ -131,6 +202,13 @@ } function animate(){ + if (!hasReachedDuration && snowflakes.length < snowflakesTargetCount){ + const nowTs = performance.now(); + while (snowflakes.length < snowflakesTargetCount && nowTs >= nextSpawnTimestamp){ + snowflakes.push(createSnowflake()); + nextSpawnTimestamp += spawnIntervalMs; + } + } updateSnowflakes(); drawSnowflakes(); // 条件判断 如果设置了有限时长则在达到时长后不再生成新粒子并等待自然落出 diff --git a/yoone-snow.php b/yoone-snow.php index 3dbbe3a..be5f035 100644 --- a/yoone-snow.php +++ b/yoone-snow.php @@ -2,7 +2,7 @@ /* Plugin Name: Yoone Snow Description: 首页 canvas 雪花效果 -Version: 1.2.0 +Version: 1.3.0 Author: Yoone */ @@ -82,16 +82,50 @@ function yoone_snow_enqueue_assets() { $media_ids = get_option('yoone_snow_media_items', array()); if (!is_array($media_ids)) { $media_ids = array(); } $media_urls = array(); + $media_weights_option = get_option('yoone_snow_media_weights', array()); + if (!is_array($media_weights_option)) { $media_weights_option = array(); } + $media_weights_by_url = array(); foreach ($media_ids as $mid) { $url = wp_get_attachment_url(intval($mid)); - if ($url) { $media_urls[] = $url; } + if ($url) { + $media_urls[] = $url; + $w = isset($media_weights_option[intval($mid)]) ? intval($media_weights_option[intval($mid)]) : 1; + if ($w < 0) { $w = 0; } + $media_weights_by_url[$url] = $w; + } + } + $default_weights = array( + 'dot' => 1, + 'flake' => 4, + 'yuanbao' => 1, + 'coin' => 1, + 'santa_hat' => 1, + 'candy_cane' => 1, + 'christmas_sock' => 1, + 'christmas_tree' => 1, + 'reindeer' => 1, + 'christmas_berry' => 1, + ); + $saved_weights = get_option('yoone_snow_shape_weights', $default_weights); + if (!is_array($saved_weights)) { $saved_weights = array(); } + $shape_weights = array(); + foreach ($default_weights as $k => $v) { + $val = isset($saved_weights[$k]) ? intval($saved_weights[$k]) : intval($v); + if ($val < 0) { $val = 0; } + $shape_weights[$k] = $val; } wp_localize_script($script_handle, 'YooneSnowSettings', array( 'selectedShapes' => $mixed_items_sanitized, 'mediaItems' => $media_urls, - // 读取并传递首页显示时长设置 单位为秒 0 表示无限 'displayDurationSeconds' => intval(get_option('yoone_snow_home_duration', 0)), - // 传递资源基础映射 用于前端按需加载 SVG 图像 + 'sizeScale' => floatval(get_option('yoone_snow_size_scale', 1.0)), + 'offsetScale' => floatval(get_option('yoone_snow_offset_scale', 1.0)), + 'radiusMin' => floatval(get_option('yoone_snow_radius_min', 1.0)), + 'radiusMax' => floatval(get_option('yoone_snow_radius_max', 3.0)), + 'driftMin' => floatval(get_option('yoone_snow_drift_min', 0.4)), + 'driftMax' => floatval(get_option('yoone_snow_drift_max', 1.0)), + 'swingMin' => floatval(get_option('yoone_snow_swing_min', 0.2)), + 'swingMax' => floatval(get_option('yoone_snow_swing_max', 1.0)), 'assetsMap' => array( 'santa_hat' => plugins_url('assets/圣诞雪帽.svg', __FILE__), 'candy_cane' => plugins_url('assets/圣诞拐杖.svg', __FILE__), @@ -100,6 +134,8 @@ function yoone_snow_enqueue_assets() { 'reindeer' => plugins_url('assets/圣诞麋鹿.svg', __FILE__), 'christmas_berry' => plugins_url('assets/圣诞果.svg', __FILE__), ), + 'shapeWeights' => $shape_weights, + 'mediaWeights' => $media_weights_by_url, )); } @@ -191,6 +227,47 @@ function yoone_snow_register_settings() { 'yoone_snow_section' ); + register_setting('yoone_snow_options', 'yoone_snow_shape_weights', array( + 'type' => 'array', + 'sanitize_callback' => function($value) { + $allowed = array('dot','flake','yuanbao','coin','santa_hat','candy_cane','christmas_sock','christmas_tree','reindeer','christmas_berry'); + $defaults = array( + 'dot' => 1, + 'flake' => 4, + 'yuanbao' => 1, + 'coin' => 1, + 'santa_hat' => 1, + 'candy_cane' => 1, + 'christmas_sock' => 1, + 'christmas_tree' => 1, + 'reindeer' => 1, + 'christmas_berry' => 1, + ); + if (!is_array($value)) { $value = array(); } + $clean = array(); + foreach ($allowed as $key) { + $num = isset($value[$key]) ? intval($value[$key]) : (isset($defaults[$key]) ? intval($defaults[$key]) : 1); + if ($num < 0) { $num = 0; } + $clean[$key] = $num; + } + return $clean; + }, + 'default' => array( + 'dot' => 1, + 'flake' => 4, + 'yuanbao' => 1, + 'coin' => 1, + 'santa_hat' => 1, + 'candy_cane' => 1, + 'christmas_sock' => 1, + 'christmas_tree' => 1, + 'reindeer' => 1, + 'christmas_berry' => 1, + ), + )); + + // 形状权重字段将移动到媒体形状字段之后 以满足界面顺序需求 + // 注册媒体形状集合 设置项保存为附件 ID 数组 register_setting('yoone_snow_options', 'yoone_snow_media_items', array( 'type' => 'array', @@ -238,6 +315,86 @@ function yoone_snow_register_settings() { 'yoone_snow_section' ); + // 注册媒体权重设置项 将附件 ID 映射到权重数值 默认 1 + register_setting('yoone_snow_options', 'yoone_snow_media_weights', array( + 'type' => 'array', + 'sanitize_callback' => function($value) { + // 将输入统一为附件 ID 到非负整数权重的映射 + if (!is_array($value)) { $value = array(); } + $clean = array(); + foreach ($value as $id => $num) { + $aid = intval($id); + $weight = intval($num); + if ($aid > 0) { + if ($weight < 0) { $weight = 0; } + $clean[$aid] = $weight; + } + } + return $clean; + }, + 'default' => array(), + )); + + // 在媒体形状字段之后渲染权重字段 包含形状权重与媒体权重 + add_settings_field( + 'yoone_snow_weights_combined', + 'Weights', + function() { + // 渲染形状权重 输入仅显示已勾选的形状 默认 1 + $selected_shapes = get_option('yoone_snow_mixed_items', array('dot','flake')); + if (is_string($selected_shapes)) { + $selected_shapes = array_filter(array_map('trim', explode(',', $selected_shapes))); + } + if (!is_array($selected_shapes)) { $selected_shapes = array('dot','flake'); } + $shape_labels = array( + 'dot' => 'Dot', + 'flake' => 'Snowflake', + 'yuanbao' => 'Yuanbao', + 'coin' => 'Coin', + 'santa_hat' => 'Santa Hat', + 'candy_cane' => 'Candy Cane', + 'christmas_sock' => 'Christmas Sock', + 'christmas_tree' => 'Christmas Tree', + 'reindeer' => 'Reindeer', + 'christmas_berry' => 'Christmas Berry', + ); + $shape_weights_current = get_option('yoone_snow_shape_weights', array()); + if (!is_array($shape_weights_current)) { $shape_weights_current = array(); } + echo '
Higher value increases selection probability 0 disables default is 1
'; + echo 'Multiply snowflake radius default is 1.0
'; + }, + 'yoone_snow', + 'yoone_snow_section' + ); + + register_setting('yoone_snow_options', 'yoone_snow_offset_scale', array( + 'type' => 'number', + 'sanitize_callback' => function($value) { + $num = floatval($value); + if ($num < 0) { $num = 0; } + return $num; + }, + 'default' => 1.0, + )); + + add_settings_field( + 'yoone_snow_offset_scale', + 'Snow Horizontal Offset Scale', + function() { + $current = floatval(get_option('yoone_snow_offset_scale', 1.0)); + echo ''; + echo 'Multiply horizontal swing amplitude default is 1.0
'; + }, + 'yoone_snow', + 'yoone_snow_section' + ); + + // 随机范围设置 注册与字段渲染 包含半径 漂移速度 摆动幅度的最小与最大 + register_setting('yoone_snow_options', 'yoone_snow_radius_min', array( + 'type' => 'number', + 'sanitize_callback' => function($value) { + $num = floatval($value); + if ($num < 0) { $num = 0; } + return $num; + }, + 'default' => 1.0, + )); + register_setting('yoone_snow_options', 'yoone_snow_radius_max', array( + 'type' => 'number', + 'sanitize_callback' => function($value) { + $min = floatval(get_option('yoone_snow_radius_min', 1.0)); + $num = floatval($value); + if ($num < $min) { $num = $min; } + return $num; + }, + 'default' => 3.0, + )); + add_settings_field( + 'yoone_snow_radius_range', + 'Radius Random Range', + function() { + $min = floatval(get_option('yoone_snow_radius_min', 1.0)); + $max = floatval(get_option('yoone_snow_radius_max', 3.0)); + echo ''; + echo ''; + echo 'Random radius in [min max] before size scale
'; + }, + 'yoone_snow', + 'yoone_snow_section' + ); + + register_setting('yoone_snow_options', 'yoone_snow_drift_min', array( + 'type' => 'number', + 'sanitize_callback' => function($value) { + $num = floatval($value); + if ($num < 0) { $num = 0; } + return $num; + }, + 'default' => 0.4, + )); + register_setting('yoone_snow_options', 'yoone_snow_drift_max', array( + 'type' => 'number', + 'sanitize_callback' => function($value) { + $min = floatval(get_option('yoone_snow_drift_min', 0.4)); + $num = floatval($value); + if ($num < $min) { $num = $min; } + return $num; + }, + 'default' => 1.0, + )); + add_settings_field( + 'yoone_snow_drift_range', + 'Drift Speed Random Range', + function() { + $min = floatval(get_option('yoone_snow_drift_min', 0.4)); + $max = floatval(get_option('yoone_snow_drift_max', 1.0)); + echo ''; + echo ''; + echo 'Random vertical drift speed base in [min max]
'; + }, + 'yoone_snow', + 'yoone_snow_section' + ); + + register_setting('yoone_snow_options', 'yoone_snow_swing_min', array( + 'type' => 'number', + 'sanitize_callback' => function($value) { + $num = floatval($value); + if ($num < 0) { $num = 0; } + return $num; + }, + 'default' => 0.2, + )); + register_setting('yoone_snow_options', 'yoone_snow_swing_max', array( + 'type' => 'number', + 'sanitize_callback' => function($value) { + $min = floatval(get_option('yoone_snow_swing_min', 0.2)); + $num = floatval($value); + if ($num < $min) { $num = $min; } + return $num; + }, + 'default' => 1.0, + )); + add_settings_field( + 'yoone_snow_swing_range', + 'Swing Amplitude Random Range', + function() { + $min = floatval(get_option('yoone_snow_swing_min', 0.2)); + $max = floatval(get_option('yoone_snow_swing_max', 1.0)); + echo ''; + echo ''; + echo 'Random horizontal swing amplitude base in [min max] before offset scale
'; + }, + 'yoone_snow', + 'yoone_snow_section' + ); } // 添加设置页面到后台菜单 条目在设置菜单下