Changeset 3446520
- Timestamp:
- 01/25/2026 12:27:38 PM (2 months ago)
- Location:
- winter-snow-effect/trunk
- Files:
-
- 3 edited
-
assets/js/snow.js (modified) (1 diff)
-
readme.txt (modified) (2 diffs)
-
winter-snow-effect.php (modified) (2 diffs)
Legend:
- Unmodified
- Added
- Removed
-
winter-snow-effect/trunk/assets/js/snow.js
r3431295 r3446520 4 4 5 5 (function () { 6 // Create canvas 7 const canvas = document.createElement('canvas'); 8 canvas.id = 'wse-snow-canvas'; 9 document.body.appendChild(canvas); 6 const startSnow = () => { 7 if (!document.body) { 8 setTimeout(startSnow, 50); 9 return; 10 } 10 11 11 const ctx = canvas.getContext('2d'); 12 let width = window.innerWidth; 13 let height = window.innerHeight; 12 // Get settings from WordPress localized script with deep fallbacks 13 const s = typeof wse_settings !== 'undefined' ? wse_settings : {}; 14 const settings = { 15 flakeCount: parseInt(s.flakeCount) || 35, 16 minSpeed: parseFloat(s.minSpeed) || 0.5, 17 maxSpeed: parseFloat(s.maxSpeed) || 1.5 18 }; 14 19 15 canvas.width = width; 16 canvas.height = height; 20 // Create canvas 21 const canvas = document.createElement('canvas'); 22 canvas.id = 'wse-snow-canvas'; 23 document.body.appendChild(canvas); 17 24 18 // Snowflakes array 19 const flakes = []; 20 // Adjust flake count based on screen width 21 // < 768px (mobile): 6 flakes (as requested) 22 // >= 768px (desktop): 35 flakes 23 const isMobile = window.innerWidth < 768; 24 const maxFlakes = isMobile ? 6 : 35; 25 const ctx = canvas.getContext('2d'); 26 let width = window.innerWidth; 27 let height = window.innerHeight; 25 28 26 // Resize handler27 window.addEventListener('resize', function () {28 width = window.innerWidth;29 height = window.innerHeight;30 29 canvas.width = width; 31 30 canvas.height = height; 32 });33 31 34 // Snowflake class 35 class Snowflake { 36 constructor() { 37 this.x = Math.random() * width; 38 this.y = Math.random() * height; 32 const isMobile = window.innerWidth < 768; 39 33 40 // Adjust size based on device 41 // Mobile: 20px - 35px (Bigger flakes) 42 // Desktop: 10px - 30px 43 this.size = isMobile 44 ? Math.random() * 15 + 20 45 : Math.random() * 20 + 10; 34 // If mobile, reduce flake count to 20% of setting (minimum 6) 35 const density = isMobile ? 0.2 : 1.0; 36 const maxFlakes = Math.max(isMobile ? 6 : 1, Math.floor(settings.flakeCount * density)); 46 37 47 this.speed = Math.random() * 1 + 0.5; // Moderate gentle speed 48 this.sway = Math.random() - 0.5; 49 this.swaySpeed = Math.random() * 0.01 + 0.005; 50 this.angle = Math.random() * Math.PI * 2; 51 this.opacity = Math.random() * 0.3 + 0.6; // Higher opacity (0.6 to 0.9) for visibility 52 } 38 // Snowflakes array 39 const flakes = []; 53 40 54 update() { 55 this.y += this.speed; 56 this.angle += this.swaySpeed; 57 this.x += Math.sin(this.angle) * 1.5; 41 // Resize handler 42 window.addEventListener('resize', function () { 43 width = window.innerWidth; 44 height = window.innerHeight; 45 canvas.width = width; 46 canvas.height = height; 47 }); 58 48 59 // Wrap around screen 60 if (this.y > height) { 61 this.y = -10; 49 // Snowflake class 50 class Snowflake { 51 constructor() { 52 this.reset(); 53 this.y = Math.random() * height; // Initial random Y 54 } 55 56 reset() { 62 57 this.x = Math.random() * width; 58 this.y = -20; 59 60 // Size: Mobile (20-35px), Desktop (10-30px) 61 this.size = isMobile 62 ? Math.random() * 15 + 20 63 : Math.random() * 20 + 10; 64 65 // Speed from settings 66 const range = Math.max(0.1, settings.maxSpeed - settings.minSpeed); 67 this.speed = Math.random() * range + settings.minSpeed; 68 69 this.swaySpeed = Math.random() * 0.01 + 0.005; 70 this.angle = Math.random() * Math.PI * 2; 71 this.opacity = Math.random() * 0.3 + 0.6; 63 72 } 64 if (this.x > width) { 65 this.x = 0; 66 } else if (this.x < 0) { 67 this.x = width; 73 74 update() { 75 this.y += this.speed; 76 this.angle += this.swaySpeed; 77 this.x += Math.sin(this.angle) * 1.5; 78 79 // Reset if out of bounds 80 if (this.y > height) { 81 this.reset(); 82 } 83 if (this.x > width) { 84 this.x = 0; 85 } else if (this.x < 0) { 86 this.x = width; 87 } 88 } 89 90 draw() { 91 ctx.font = `${this.size}px sans-serif`; 92 ctx.fillStyle = `rgba(255, 255, 255, ${this.opacity})`; 93 ctx.shadowColor = 'rgba(0, 0, 0, 0.3)'; 94 ctx.shadowBlur = 4; 95 ctx.fillText('*', this.x, this.y); 96 ctx.shadowBlur = 0; 68 97 } 69 98 } 70 99 71 draw() { 72 ctx.font = `${this.size}px sans-serif`; 73 ctx.fillStyle = `rgba(255, 255, 255, ${this.opacity})`; 100 // Initialize flakes 101 for (let i = 0; i < maxFlakes; i++) { 102 flakes.push(new Snowflake()); 103 } 74 104 75 // Shadow for visibility 76 ctx.shadowColor = 'rgba(0, 0, 0, 0.3)'; 77 ctx.shadowBlur = 4; 105 // Animation loop 106 function animate() { 107 ctx.clearRect(0, 0, width, height); 108 flakes.forEach(flake => { 109 flake.update(); 110 flake.draw(); 111 }); 112 requestAnimationFrame(animate); 113 } 78 114 79 ctx.fillText('*', this.x, this.y); 115 animate(); 116 }; 80 117 81 // Reset shadow to avoid affecting other potential draws if shared context (good practice) 82 ctx.shadowBlur = 0; 83 } 118 // Run when ready 119 if (document.readyState === 'complete' || document.readyState === 'interactive') { 120 startSnow(); 121 } else { 122 document.addEventListener('DOMContentLoaded', startSnow); 84 123 } 85 86 // Initialize flakes87 for (let i = 0; i < maxFlakes; i++) {88 flakes.push(new Snowflake());89 }90 91 // Animation loop92 function animate() {93 ctx.clearRect(0, 0, width, height);94 flakes.forEach(flake => {95 flake.update();96 flake.draw();97 });98 requestAnimationFrame(animate);99 }100 101 animate();102 124 })(); -
winter-snow-effect/trunk/readme.txt
r3431295 r3446520 4 4 Requires at least: 5.0 5 5 Tested up to: 6.9 6 Stable tag: 1. 16 Stable tag: 1.2.2 7 7 Requires PHP: 7.0 8 8 License: GPLv2 or later 9 9 License URI: https://www.gnu.org/licenses/gpl-2.0.html 10 10 11 Automatically adds a falling snow effect to your website only during winter months (December, January, February).11 Automatically adds a customizable falling snow effect to your website. 12 12 13 13 == Description == 14 14 15 Bring the winter spirit to your WordPress site with the Winter Snow Effect plugin. This lightweight plugin a utomatically detects the current month and enables a beautiful, non-intrusive falling snow animation during the winter season (December, January, and February).15 Bring the winter spirit to your WordPress site with the Winter Snow Effect plugin. This lightweight plugin allows you to enable a beautiful, non-intrusive falling snow animation during the winter season or any custom date range you choose. 16 16 17 17 **Features:** 18 * **Automatic Detection:** Activates only during winter months. 18 * **Customizable Timing:** Choose specific months or a custom date range for the snow effect. 19 * **Performance Controls:** Adjust the number of snowflakes to balance visuals and site speed. 20 * **Visual Customization:** Control the falling speed of the snow. 19 21 * **Lightweight:** Minimal CSS and JavaScript for optimal performance. 20 * **Responsive:** optimized for smartphones and tablets. 21 * **No Configuration Needed:** Simply install and activate. 22 * **Responsive:** Automatically optimized for smartphones and tablets. 22 23 23 24 == Installation == … … 25 26 1. Upload the plugin files to the `/wp-content/plugins/winter-snow-effect` directory, or install the plugin through the WordPress plugins screen directly. 26 27 2. Activate the plugin through the 'Plugins' screen in WordPress. 27 3. Enjoy the snow during the winter months!28 3. Navigate to **Settings > Winter Snow** to customize your effect. 28 29 29 30 == Frequently Asked Questions == 30 31 31 32 = When does the snow appear? = 32 The snow effect is active only during December, January, and February.33 By default, the snow appears in December, January, and February. You can change this in the plugin settings to any combination of months or a specific date range. 33 34 34 = Can I disable it? =35 Deactivate the plugin to stop the snow effect.35 = Can I control how much snow is shown? = 36 Yes, the settings page allows you to adjust the flake count and speed. 36 37 37 38 == Changelog == 39 40 = 1.2 = 41 * New: Added Settings Page under Settings > Winter Snow. 42 * New: Support for Custom Date Ranges (Start/End dates). 43 * New: Customizable flake count and falling speed. 44 * Refactor: Modernized PHP code structure using a class-based approach. 38 45 39 46 = 1.1 = -
winter-snow-effect/trunk/winter-snow-effect.php
r3431295 r3446520 3 3 Plugin Name: Winter Snow Effect 4 4 Description: Automatically adds a falling snow effect to your website only during winter months (December, January, February). 5 Version: 1. 15 Version: 1.2.2 6 6 Author: Sarangan Thillaiampalam 7 7 Author URI: https://sarangan.dk … … 13 13 } 14 14 15 /** 16 * Check if the current month is a winter month (Dec, Jan, Feb). 17 * 18 * @return bool True if winter, false otherwise. 19 */ 20 function wse_is_winter() { 21 $current_month = (int) gmdate( 'n' ); 22 // 12 = December, 1 = January, 2 = February 23 return in_array( $current_month, array( 12, 1, 2 ), true ); 15 class WinterSnowEffect { 16 17 private $options; 18 19 public function __construct() { 20 add_action( 'admin_menu', array( $this, 'add_plugin_page' ) ); 21 add_action( 'admin_init', array( $this, 'page_init' ) ); 22 add_action( 'wp_enqueue_scripts', array( $this, 'enqueue_scripts' ) ); 23 24 // Add settings link on the plugins page 25 $plugin_basename = plugin_basename( __FILE__ ); 26 add_filter( "plugin_action_links_{$plugin_basename}", array( $this, 'add_settings_link' ) ); 27 } 28 29 /** 30 * Add options page 31 */ 32 public function add_plugin_page() { 33 add_options_page( 34 'Settings Admin', 35 'Winter Snow', 36 'manage_options', 37 'wse-setting-admin', 38 array( $this, 'create_admin_page' ) 39 ); 40 } 41 42 /** 43 * Options page callback 44 */ 45 public function create_admin_page() { 46 $this->options = get_option( 'wse_settings' ); 47 ?> 48 <div class="wrap"> 49 <h1>Winter Snow Effect Settings</h1> 50 <form method="post" action="options.php"> 51 <?php 52 settings_fields( 'wse_option_group' ); 53 do_settings_sections( 'wse-setting-admin' ); 54 submit_button(); 55 ?> 56 </form> 57 </div> 58 <?php 59 } 60 61 /** 62 * Register and add settings 63 */ 64 public function page_init() { 65 register_setting( 66 'wse_option_group', 67 'wse_settings', 68 array( $this, 'sanitize' ) 69 ); 70 71 add_settings_section( 72 'setting_section_id', 73 'General Settings', 74 array( $this, 'print_section_info' ), 75 'wse-setting-admin' 76 ); 77 78 add_settings_field( 79 'display_mode', 80 'Display Mode', 81 array( $this, 'display_mode_callback' ), 82 'wse-setting-admin', 83 'setting_section_id' 84 ); 85 86 add_settings_field( 87 'months', 88 'Active Months (Standard Mode)', 89 array( $this, 'months_callback' ), 90 'wse-setting-admin', 91 'setting_section_id' 92 ); 93 94 add_settings_field( 95 'custom_range', 96 'Custom Date Range', 97 array( $this, 'custom_range_callback' ), 98 'wse-setting-admin', 99 'setting_section_id' 100 ); 101 102 add_settings_field( 103 'flake_count', 104 'Flake Count', 105 array( $this, 'flake_count_callback' ), 106 'wse-setting-admin', 107 'setting_section_id' 108 ); 109 110 add_settings_field( 111 'flake_speed', 112 'Min/Max Speed', 113 array( $this, 'flake_speed_callback' ), 114 'wse-setting-admin', 115 'setting_section_id' 116 ); 117 } 118 119 /** 120 * Sanitize each setting field as needed 121 */ 122 public function sanitize( $input ) { 123 $new_input = array(); 124 125 $new_input['display_mode'] = isset( $input['display_mode'] ) ? sanitize_text_field( $input['display_mode'] ) : 'standard'; 126 127 if ( isset( $input['months'] ) && is_array( $input['months'] ) ) { 128 $new_input['months'] = array_map( 'intval', $input['months'] ); 129 } else { 130 $new_input['months'] = array(); 131 } 132 133 $new_input['start_date'] = isset( $input['start_date'] ) ? sanitize_text_field( $input['start_date'] ) : ''; 134 $new_input['end_date'] = isset( $input['end_date'] ) ? sanitize_text_field( $input['end_date'] ) : ''; 135 136 $new_input['flake_count'] = isset( $input['flake_count'] ) ? absint( $input['flake_count'] ) : 35; 137 138 // Handle decimal commas (common in many locales) by converting to dots 139 $min_raw = isset( $input['min_speed'] ) ? str_replace( ',', '.', $input['min_speed'] ) : '0.5'; 140 $max_raw = isset( $input['max_speed'] ) ? str_replace( ',', '.', $input['max_speed'] ) : '1.5'; 141 142 $new_input['min_speed'] = floatval( $min_raw ); 143 $new_input['max_speed'] = floatval( $max_raw ); 144 145 // Ensure max is not less than min 146 if ( $new_input['max_speed'] < $new_input['min_speed'] ) { 147 $new_input['max_speed'] = $new_input['min_speed'] + 1.0; 148 } 149 150 return $new_input; 151 } 152 153 public function print_section_info() { 154 print 'Configure when and how the snow effect appears on your site.'; 155 } 156 157 public function display_mode_callback() { 158 $options = get_option( 'wse_settings' ); 159 $mode = isset( $options['display_mode'] ) ? $options['display_mode'] : 'standard'; 160 ?> 161 <select id="display_mode" name="wse_settings[display_mode]"> 162 <option value="standard" <?php selected( $mode, 'standard' ); ?>>Standard (Selected Months)</option> 163 <option value="custom" <?php selected( $mode, 'custom' ); ?>>Custom Date Range</option> 164 </select> 165 <?php 166 } 167 168 public function months_callback() { 169 $options = get_option( 'wse_settings' ); 170 $saved_months = isset( $options['months'] ) ? (array) $options['months'] : array( 12, 1, 2 ); 171 $months = array( 172 1 => 'January', 2 => 'February', 3 => 'March', 4 => 'April', 173 5 => 'May', 6 => 'June', 7 => 'July', 8 => 'August', 174 9 => 'September', 10 => 'October', 11 => 'November', 12 => 'December' 175 ); 176 177 foreach ( $months as $num => $name ) { 178 printf( 179 '<label style="margin-right: 15px;"><input type="checkbox" name="wse_settings[months][]" value="%s" %s /> %s</label>', 180 $num, 181 checked( in_array( $num, $saved_months ), true, false ), 182 $name 183 ); 184 if ( $num % 3 === 0 ) echo '<br/>'; 185 } 186 } 187 188 public function custom_range_callback() { 189 $options = get_option( 'wse_settings' ); 190 $start_date = isset( $options['start_date'] ) ? $options['start_date'] : ''; 191 $end_date = isset( $options['end_date'] ) ? $options['end_date'] : ''; 192 ?> 193 <label>Start: <input type="date" name="wse_settings[start_date]" value="<?php echo esc_attr( $start_date ); ?>" /></label> 194 <label style="margin-left: 20px;">End: <input type="date" name="wse_settings[end_date]" value="<?php echo esc_attr( $end_date ); ?>" /></label> 195 <p class="description">Only used if Display Mode is set to "Custom Date Range".</p> 196 <?php 197 } 198 199 public function flake_count_callback() { 200 $options = get_option( 'wse_settings' ); 201 $count = isset( $options['flake_count'] ) ? $options['flake_count'] : 35; 202 ?> 203 <input type="number" name="wse_settings[flake_count]" value="<?php echo esc_attr( $count ); ?>" min="1" max="200" /> 204 <p class="description">Recommended: 20-50. High values may affect performance.</p> 205 <?php 206 } 207 208 public function flake_speed_callback() { 209 $options = get_option( 'wse_settings' ); 210 $min_speed = isset( $options['min_speed'] ) ? $options['min_speed'] : 0.5; 211 $max_speed = isset( $options['max_speed'] ) ? $options['max_speed'] : 1.5; 212 ?> 213 Min: <input type="number" step="0.1" name="wse_settings[min_speed]" value="<?php echo esc_attr( $min_speed ); ?>" /> 214 Max: <input type="number" step="0.1" name="wse_settings[max_speed]" value="<?php echo esc_attr( $max_speed ); ?>" /> 215 <?php 216 } 217 218 /** 219 * Check if snow should be shown based on settings 220 */ 221 public function should_show_snow() { 222 $options = get_option( 'wse_settings' ); 223 224 // Ensure options is an array for safe index access 225 if ( ! is_array( $options ) ) { 226 $options = array(); 227 } 228 229 $mode = isset( $options['display_mode'] ) ? $options['display_mode'] : 'standard'; 230 231 if ( $mode === 'custom' ) { 232 $start = isset( $options['start_date'] ) ? $options['start_date'] : ''; 233 $end = isset( $options['end_date'] ) ? $options['end_date'] : ''; 234 235 if ( empty( $start ) || empty( $end ) ) { 236 return false; 237 } 238 239 // Use site local time for comparison if possible, otherwise gmdate 240 $today = current_time( 'Y-m-d' ); 241 return ( $today >= $start && $today <= $end ); 242 } else { 243 // Standard mode: check current month 244 $current_month = (int) current_time( 'n' ); 245 $saved_months = isset( $options['months'] ) ? (array) $options['months'] : array( 12, 1, 2 ); 246 247 // If saved_months is set but empty (user unchecked all), snow won't show. 248 // However, if the key is missing (fresh install), it uses the fallback. 249 return in_array( $current_month, $saved_months ); 250 } 251 } 252 253 /** 254 * Enqueue scripts and styles 255 */ 256 public function enqueue_scripts() { 257 if ( $this->should_show_snow() ) { 258 $options = get_option( 'wse_settings' ); 259 if ( ! is_array( $options ) ) { 260 $options = array(); 261 } 262 263 wp_enqueue_style( 'wse-snow-style', plugin_dir_url( __FILE__ ) . 'assets/css/snow.css', array(), '1.2.1' ); 264 wp_enqueue_script( 'wse-snow-script', plugin_dir_url( __FILE__ ) . 'assets/js/snow.js', array(), '1.2.1', true ); 265 266 // Pass settings to JS 267 wp_localize_script( 'wse-snow-script', 'wse_settings', array( 268 'flakeCount' => isset( $options['flake_count'] ) ? (int) $options['flake_count'] : 35, 269 'minSpeed' => isset( $options['min_speed'] ) ? (float) $options['min_speed'] : 0.5, 270 'maxSpeed' => isset( $options['max_speed'] ) ? (float) $options['max_speed'] : 1.5, 271 ) ); 272 } 273 } 274 /** 275 * Add settings link to the plugins page 276 */ 277 public function add_settings_link( $links ) { 278 $settings_link = '<a href="options-general.php?page=wse-setting-admin">' . __( 'Settings' ) . '</a>'; 279 array_unshift( $links, $settings_link ); 280 return $links; 281 } 24 282 } 25 283 26 /** 27 * Enqueue scripts and styles only if it is winter. 28 */ 29 function wse_enqueue_scripts() { 30 if ( wse_is_winter() ) { 31 wp_enqueue_style( 'wse-snow-style', plugin_dir_url( __FILE__ ) . 'assets/css/snow.css', array(), '1.1' ); 32 wp_enqueue_script( 'wse-snow-script', plugin_dir_url( __FILE__ ) . 'assets/js/snow.js', array(), '1.1', true ); 33 } 34 } 35 add_action( 'wp_enqueue_scripts', 'wse_enqueue_scripts' ); 284 new WinterSnowEffect();
Note: See TracChangeset
for help on using the changeset viewer.