Плавная подмена изображений на чистом JS

4 Июн
2012

Недавно начальством была поставлена задача сделать скрипт на сайте, который будет плавно переключать одну картинку на другую используя некоторый список изображений. Казалось бы, всё очень просто, есть JQuery и куча плагинов к нему, но как всегда начальство ставит неординарные задачи. Всё должно быть реализовано на чистом JavaScript без использования библиотек.
Изначально на просторах интернета был найден простенький скрипт:
var duration = 1000;
var hidetime = 2000;
var showtime = 2000;
var block = null;

function InitFade()
{
    block = document.getElementById("block");
    setTimeout("fadeIn()",1000);
}

function fadeIn()
{
    for (var i =0; i <= 1; i += 0.01)
    {
        setTimeout("setOpacity(" + (1 - i) + ")", duration * i);
    }

    setTimeout("fadeOut()",duration + hidetime);
}

function fadeOut()
{
    for (var i = 0; i <= 1; i += 0.01)
    {
        setTimeout("setOpacity(" + i + ")", duration * i);
    }

    setTimeout("fadeIn()", duration + showtime);
}

function setOpacity(opa)
{
    block.style.opacity = opa;
    block.style.MozOpacity = opa;
    block.style.filter = 'alpha(opacity='+ ( opa * 100 ) + ');';
}

window.onload = InitFade;
Начало положено, однако задача была поставлена немного другая.
Для начала надо было определиться, откуда же брать список картинок. Чтобы упростить интеграцию с существующей системой было решено выводить в html адреса картинок, а потом забирать их непосредственно в массив. Так же нам понадобится переменная текущей позиции в этом массиве и блок, в котором непосредственно будет производиться ротация.
После обсуждения с начальством было решено добавить к функциональности такую вещь, как остановка ротации. Для этого была добавлена ещё одна переменная, в которой хранятся все идентификаторы setTimeout();
После разбора требуемых параметров можно приступать непосредственно к продумыванию логики.
Ротация картинок это прежде всего цикл, но как реализовать цикл с задержками в JavaScript? И тут на помощь приходит предыдущий пример. Сама реализация находится внутри цикла в функциях fadeIn/fadeOut. Т. е. к каждому последующему тику счётчика, начиная от текущего момента и заканчивая 1 секундой высчитывется значение прозрачночти и устанавливается в стилях блока. По сути получается каскад задержек, которые постепенно сводят прозрачность к нулю. Для остановки же ротации надо просто очистить все задержки и установить прозрачность равную 1му.
С логикой разобрались, теперь непосредственно реализация:
var gImages =	Array(); // Массив изображений
var gCurPos = 0; // Текущая позиция в массиве
var gImageBlock = null; // Блок с картинкой для ротации
var gTimeOutArr = Array(); //Массив с задержками

function rotateImages() // Функция, инициализирующая ротацию
{
    for (var i = 0; i < 12; i++) // Имеем 12 картинок
    {
        var div = document.getElementById("block_" + i);
        var divs = div.getElementsByTagName("div")[0];

        gImages.push(divs.innerHTML); // Достаём картинки из HTML и записываем в массив
    }

    gImageBlock = document.getElementById("foto"); // Получаем непосредственно блок для ротации
    for (var i = 0; i < 4; i++) // Инициализируем массивы для задержек
        gTimeOutArr.push(Array());

    // 0 - задержки для функций скрытия/показа
    // 1 - задержки непосредственно для скрытия
    // 2 - задержки непосредственно для показа
    // 3 - задержка перед следующей ротацией

    switchImages(); // Запуск ротации
}

function switchImages()
{
    for (var i = 0; i < gTimeOutArr.length; i++) // Очистка задержек
        clearTimeOuts(i);

    gTimeOutArr[0].push(setTimeout(fadeIn,1000)); // Запуск угасания картинки
    gTimeOutArr[0].push(setTimeout(fadeOut,3000)); // Запуск появления картинки
}
function fadeIn()
{
    var duration = 1000; // Длительность угасания
    for (var i = 0; i <= 1; i += 0.01) // Установка задержек и значений для угасания
    {
        gTimeOutArr[1].push(setTimeout("setOpacity(" + (1 - i) + ")",duration * i)); // (1 - i) используется как раз для того, чтобы время задержки увеличивалось, а значение уменьшалось
    }
}

function fadeOut()
{
    gCurPos = (gCurPos + 1 >= gImages.length ? 0 : gCurPos + 1); // Проверка позиции в массиве

    setBlock(gCurPos); // Установка значений массива

    var duration = 1000; // Время выполнения
    var hidetime = 2000; // Задержка до следующей ротации
    for (var i = 0; i <= 1; i += 0.01) // Тоже самое, как и в fadeIn
    {
        gTimeOutArr[2].push(setTimeout("setOpacity(" + i + ")",duration * i));
    }

    gTimeOutArr[3].push(setTimeout("switchImages()",hidetime)); // Следующая ротация
}

function setBlock(num) // Установка значений блока
{
    gCurPos = num; // Текущая позиция
    for (var i = 0; i < 12; i++) // Установка определённого класса для всех объектов и выделение требуемого
        if (i == gCurPos) document.getElementById("block_" + i).style.textDecoration = "underline";
        else document.getElementById("block_" + i).style.textDecoration = "none";

    gImageBlock.className = "section_" + (num + 1); // Установка класса для блока с картинкой
    gImageBlock.getElementsByTagName("img")[0].src = gImages[num]; // Задание непосредственно картинки
    document.getElementById("about").innerHTML = "

" + document.getElementById("block_"+ num).getElementsByTagName("h4")[0].innerHTML + "

" + document.getElementById("block_" + num).getElementsByTagName("p")[0].innerHTML; // Добавление требуемого контента } function setOpacity(opa) // Установка прозрачности { gImageBlock.style.opacity = opa; // Основной метод gImageBlock.style.MozOpacity = opa; // для -moz-opacity gImageBlock.style.filter = 'alpha(opacity=' + (opa * 100) + ');'; // Для IE } function stopRotate() // Остановка ротации { for (var i = 0; i < gTimeOutArr.length; i++) clearTimeOuts(i); setOpacity(1); } function clearTimeOuts(num) // Очистка задержек { for (var j = 0; j < gTimeOutArr[num].length; j++) clearTimeout(gTimeOutArr[num][j]); gTimeOutArr[num] = Array(); } setTimeout("rotateImages()",1500);
В итоге мы имеем то, что требуется. Есть некий список картинок, из которого постоянно берётся следующий элемент и подменяется текущий + возможность навести на интересующий элемент и зафиксировать ротацию.
Живой Пример.
По материалам Хабрахабр.



загрузка...

Комментарии:

Наверх