var snowfall = new function()
{
// Объявление конфигурационного объекта
var settings = {};
// Настройки
settings['use_images'] = true; // Использовать ли изображения
settings['flake_symbol'] = "*"; // Символ "снежинки"
settings['flakes_dir_name'] = "snow"; // Имя папки с изображениями
settings['flake_imgs_ext'] = "gif"; // Расширения
settings['flake_types_num'] = 3; // Количество "видов" снежинок
settings['flake_objects_num'] = 15; // Количество "объектов" снежинок
settings['flake_symbol_color'] = 'blue'; // Цвет текстовых снежинок
settings['doctype'] = 'html'; // Ваш доктайп (если он не указан не изменяйте эту опцию).
// Возможные значения: xhtml || html
settings['update_positions_interval'] = 20; //Интервал обновления позиций снежинок (в миллисекундах)
//по умолчанию -- 40
// Константы
var snow_consts = {};
snow_consts["borderForce"] = 0.01; //Сила отталкивания от краёв; изменять именно эту константу
snow_consts["g"] = 54;
snow_consts["m"] = 0.1;
snow_consts["k"] = 0.1;
snow_consts["F"] = 20;
snow_consts["dt"] = 1;
snow_consts["mouseX"] = -1000;
snow_consts["mouseY"] = -1000;
// Интервал для вызова метода flakes_positions
var positions;
//Статус снегопада (идет; не идет)
var status = false;
/**
* Кэшируем изображения если они включены.
*/
if (settings['use_images'])
{
var imgs = new Array();
for (var numimg = 1; numimg <= settings['flake_types_num']; numimg++)
{
imgs[numimg] = new Image();
imgs[numimg].src = settings['flakes_dir_name'] + '/' + numimg + '.' + settings['flake_imgs_ext'];
}
}
/**
* Метод изменит настройки скрипта,
* если переданные ему настройки валидные.
*/
var set_settings = function(new_settings)
{
if (new_settings)
{
if (typeof new_settings['use_images'] != 'boolean' || typeof new_settings['flake_symbol'] != 'string'
|| typeof new_settings['flakes_dir_name'] != 'string' || typeof new_settings['flake_imgs_ext'] != 'string'
|| typeof new_settings['flake_types_num'] != 'number' || typeof new_settings['flake_objects_num'] != 'number'
|| typeof new_settings['flake_symbol_color'] != 'string' || typeof new_settings['doctype'] != 'string'
|| typeof new_settings['update_positions_interval'] != 'number')
{
return false;
} else {
settings = new_settings;
}
}
return true;
}
/**
* Метод изменит значение переменных
* snow_consts["mouseX"] и snow_consts["mouseY"] записав в них
* координаты мыщи.
*/
var mouse_Coords = function(event)
{
var event = event || window.event;
snow_consts["mouseX"] = event.clientX;
snow_consts["mouseY"] = event.clientY;
}
document.getElementsByTagName("body")[0].onmousemove = mouse_Coords;
/**
* Метод создает settings['flake_objects_num'] снежинок
* задавая им все необходимые свойства.
*/
var create_flakes = function()
{
var clientWidth = document.getElementsByTagName("body")[0].clientWidth;
var clientHeight = document.getElementsByTagName("body")[0].clientHeight;
var body_element = document.getElementsByTagName("body")[0];
for (var id=1; id<=settings['flake_objects_num']; id++) /* На каждой итерации цикла создается снежинка */
{
var flake_tag = 0;
if (settings['use_images']) // Выбор тега снежинки в зависимсти от опции settings['use_images']
{
flake_tag = 'img';
} else {
flake_tag = 'div';
}
flake_obj = document.createElement(flake_tag); /* Задаются все необходимые свойства. */
if (settings['use_images']) /* Создание объекта снежинки в зависимости от опции settings['use_images'] */
{
var random_num = Math.floor(Math.random() * settings['flake_types_num']) + 1;
flake_obj.src = imgs[random_num].src;
flake_obj.alt = "flake" + id;
} else {
flake_obj.appendChild(document.createTextNode(settings['flake_symbol']));
}
flake_obj.id = 'flake'+id;
flake_obj.style.color = settings['flake_symbol_color'];
var flake_obj = body_element.appendChild(flake_obj); /* Вставляем нашу снежинки в тег body */
flake_obj.halfWidth = flake_obj.clientWidth/2; /* Радиус снежинки */
flake_obj.halfHeight = flake_obj.clientHeight/2;/* Высота снежинки */
flake_obj.style.position = "absolute";
flake_obj.left = Math.random() * (clientWidth - flake_obj.halfWidth); /* Два специальных свойства с целью работы скорости снежинок, так как style.left и top может хранить только целые значения. */
flake_obj.top = Math.random() * (clientHeight - flake_obj.halfHeight - snow_consts["g"]);
flake_obj.amplitude = 1 + Math.random(); /* Отклонение от оси */
flake_obj.speed = 1 + Math.random() * 0.2; /* Скорость падения */
flake_obj.tempo = 2*Math.PI/(80 + 80 * Math.random()); /* Скорость покачивания */
flake_obj.speedX = 0; /* В этих свойствах ранится разгон */
flake_obj.speedY = 0;
}
}
var delete_flakes = function()
{
var body_element = document.getElementsByTagName("body")[0];
for (var id=1; id<=settings['flake_objects_num']; id++)
{
var flake_obj = document.getElementById('flake' + id);
body_element.removeChild(flake_obj);
}
}
var flakes_positions = function()
{
var clientWidth = document.getElementsByTagName("body")[0].clientWidth; /* Переменные для удобства */
var clientHeight = document.getElementsByTagName("body")[0].clientHeight;
var scrollLeft = document.getElementsByTagName("body")[0].scrollLeft;
if (settings['doctype'] === 'html')
{
var scrollTop = document.getElementsByTagName("body")[0].scrollTop;
} else {
var scrollTop = document.documentElement.scrollTop;
}
for (var i=1; i<=settings['flake_objects_num']; i++) /* Изменение положения снежинки на итерации цикла */
{
var flake_obj = document.getElementById('flake'+i); /* Получаем объект снежинки */
flake_obj.left += (flake_obj.speedX + flake_obj.amplitude*Math.cos(flake_obj.top*flake_obj.tempo))*snow_consts["dt"];
/* Выше! Это свойство создано с целью работы разных скоростей снежинок так как style.left может хранить только
цельные значения. */
flake_obj.top += (flake_obj.speedY + flake_obj.speed)*snow_consts["dt"];
/* Выше! Это свойство создано с целью работы разных скоростей снежинок так как style.left может хранить только
цельные значения. */
if (flake_obj.top < - snow_consts["g"]) /* Проверка не вышла ли снежинка за край экрана */
{
flake_obj.top = -snow_consts["g"];
flake_obj.speedX = flake_obj.speedY = 0; /* Обнуляем разгон! */
} else {
if (flake_obj.top > (clientHeight - snow_consts["g"])) /* Снежинка вышла за край изменяем положение. */
{
flake_obj.style.top = scrollTop;
flake_obj.top = - snow_consts["g"];
flake_obj.speedX = flake_obj.speedY = 0; /* Обнуляем разгон! */
flake_obj.style.left = Math.floor(flake_obj.left = Math.random() * (clientWidth - flake_obj.halfWidth)) + scrollLeft;
}
}
var deltaX = flake_obj.left + flake_obj.halfWidth - snow_consts["mouseX"]; /* Начинаем вычислять left и top координаты в зависимости от положения мыщи */
var deltaY = flake_obj.top + flake_obj.halfHeight/2 - snow_consts["mouseY"];
var Fx_old = snow_consts["F"] * deltaX/(deltaX*deltaX + deltaY*deltaY) - snow_consts["k"]*flake_obj.speedX;
var Fx = Fx_old + snow_consts["borderForce"] * (Math.max(snow_consts["g"] - flake_obj.left, 0) - Math.max(flake_obj.left - clientWidth + 2*snow_consts["g"], 0));
var Fy = snow_consts["F"] * deltaY/(deltaX*deltaX + deltaY*deltaY) - snow_consts["k"]*flake_obj.speedY;
flake_obj.speedX += Fx/snow_consts["m"]*snow_consts["dt"];
flake_obj.speedY += Fy/snow_consts["m"]*snow_consts["dt"];
flake_obj.style.left = scrollLeft + Math.round(flake_obj.left) + 'px'; /* Устанавливаем координаты! */
flake_obj.style.top = scrollTop + Math.round(flake_obj.top) + 'px';
}
}
this.start = function(new_settings)
{
if (status)
{
this.stop();
}
//Вызовем метод сет сеттингс, если настройки переданы в качестве аргумента методу start
//и они валидные -- то он изменит настройки скрипта.
if (!set_settings(new_settings))
{
throw new Error('Настройки, переданные методу snowfall::start() не валидные!');
}
create_flakes(); /* Создаем снежинки */
positions = setInterval(flakes_positions, settings['update_positions_interval']); /* Запускаем метод flakes_positions каждые 40 миллисекунд */
status = true;
}
this.stop = function()
{
if (!status) return;
clearInterval(positions);
delete_flakes();
status = false;
}
}
snowfall.start();