Слайд-шоу с мульти-переходами

В примерах DHTML кода я уже показывал как делать переходы между двумя картинками в одном и том же месте. Здесь я хочу подробно объяснить как можно сделать непрерывно работающее на сайте слайд-шоу, в котором серия картинок сменяет друг друга в одном и том же месте сайта в окне с рамкой. Код будет с самого начала написан в таком виде, чтобы иметь возможность дать пользователю управлять им через кнопки, но сначала мы рассмотрим сам процесс показа, а методы управления будут описаны в другой статье. Код, который я здесь представил, я придумал сам, и он отличается от других вариантов, которые при желании можно найти в интернете. Более того, это некий частный случай, вариантов можно придумать намного больше. И сам код можно написать разными способами. Возможно со временем это все будет рассмотрено, а здесь представлен конкретный вариант, который все равно достаточно сложный и его описание представляет собой нелегкую задачу.

Идея данного варианта следующая. Я хочу манипулировать с двумя последовательными картинками, адреса которых указывают на интернет и находятся в массиве текстов, то есть записаны как текстовые строки. Есть старая картинка и есть новая картинка. Серия переходов может показывать как новая картинка постепенно наползает на место старой. Она может двигаться по 8-ми направлениям как вдоль сторон прямоугольника в обоих направлениях, так и по диагонали. В каждый момент видна только часть новой картинки, которая попадает в окно показа. Такие переходы проще всего программировать, но движение картинки вызывает утомление глаз, как и любые быстрые перемещения предметов на экране. Такие переходы хорошо бы иметь, но не всегда следует их применять. Другая серия переходов может быть связана с выталкиванием картинки. То есть старая картинка постепенно выходит из окна показа, а вслед за ней входит новая. Это выглядит как выталкивание одного слайда другим в диапроекторе. Таких переходов может быть 4 вдоль сторон прямоугольника в двух направлениях. Они тоже напрягают глаза, но выглядят эффектно.

Следующая серия переходов может быть такой, что обе картинки стоят в окне на своем месте, но новая картинка показывается кусочками, как бы в двигающейся рамке. Таких переходов может быть тоже 8 и они отличаются от первой серии тем, что здесь двигается рамка над верхней картинкой, а это не так напрягает глаза. Далее, можно сделать переход, когда рамка увеличивается в размерах из центра, где она сначала имеет нулевые размеры. При этом новая картинка как бы разворачивается над старой. И можно сделать обратный переход, когда новая картинка находится полд старой, а старая сворачивается к центру, то есть схлопывается, открывая новую картинку. Также можно включить переход, связанный с изменением прозрачности верхней картинки от максимальной (полностью прозрачная) до нуля (полностью непрозрачная). Наконец можно придумать такой переход, когда над старой картинкой открывается окно произвольных размеров, через которое показывается движущаася картинки, например содержащая фасонный текст. Таких движений можно сделать 4 по сторонам окна. Движущаяся картинка может иметь произвольные размеры, в том числе очень большие.

Так как в нашем распоряжении имеется всего один инструмент: повторный запуск функции с помощью оператора setTimeout(move,pause), то необходимо так написать функцию move, чтобы она бесконечно долго сменяла кадры различным образом, да еще делала фасонные переходы. Но я еще хочу предусмотреть возможность останавливать анимацию в любой момент и запускать ее снова, а также крутить кадры как в прямом, так и в обратном направлении. И, более того, иметь возможность не ждать полное время показа любого кадра, а сразу переходить к новому кадру по клику кнопки. Ясно, что сделать это в инкапсулированном виде очень сложно, намного проще все сделать используя глобальные переменные. Соответственно у нас будут логические переменные ona$, key$, dir$, nex$. Первая, если равна false, будет останавливать анимацию и запускать ее снова, если равна true. Вторая будет делить процесс на две части, установочную, если равна true, и переходную, если равна false. Третья будет задавать направление смены кадров: прямое если равна true, обратное если равна false. Наконец, последняя будет реализовывать быстрый переход к следущему кадру, если равна true.

Так как в первой установочной части функции будут определяться некоторые переменные, которые потом будут использоваться во второй переходной части через какое то время, то все эти переменные также должны быть глобальными. Они не должны терять своих значений при окончании работы функции. Все глобальные переменные должны быть уникальными и не использовать в любых других частях кода. Поэтому я буду ставить в конце имен этих переменных знак $, а в именах не буду использовать числа. Это решает две задачи. Первая уменьшает вероятность того, что если бесплатный сервер прибавит к вашему сайту свой javascript код, то имена переменных в нем не совпадут с вашими и конфликта не будет. Вторая дает возможность ставить на сайт две и более анимаций. Достаточно сделать замену символа $ на $1 в любом текстовом редакторе, и мы получаем копию кода с независимыми переменными и функциями, которая сможет крутить новую анимацию.

Код данного примера имеет довольно большие размеры, поэтому я не буду показывать его целиком, а буду ставить последовательные части и объяснять каждую из них. А весь код можно получить сразу если запустить пример по этой ссылке и попросить браузер показать исходный код. Альтерантивно можно сохранить страницу в файл и затем просмотреть ее код в текстовом редакторе. В обоих случаях в конце кода будет кусок, приписанный Яндексом, но его легко распознать и уничтожить. Итак начнем смотреть код.
Первая часть кода показывает структуру сайта и предварительную функцию задания входных параметров. Это так называемая неуниверсальная часть, ее необходимо переписывать при переходе к новой анимации или изменении ее фасона. Как обычно весь объект помещается в главную div область с относительным позиционирование по центру окна браузера (id=mww0). Внутри нее ставится первая div область для нижней картинки (id=pho0), внктри которой ставится сама картинка с id=bgi0. Далее внутри ставится вторая div область для верхней картинки (id=obj0), внутри которой ставится div область рамы с id=img0, а уже внутри рамы сама картинка с id=fgi0. Под окном анимации ставится параграф текста с id=paa0. Все области пустые. В теге style выполняется CSS форматирование областей анимации. Все три области позиционируются абсолютно. Главная область и область рамы второй картинки закрывают все за пределами областей (display:block; overflow:hidden). Вот и вся структура сайта. Конечно это минималисткая структура, реально на сайте будут кнопки, проигрываетль музыки, тексты, но наша цель: описать javascript код, и вот он как раз почти полный.

Итак, переходим к описанию javascript кода. Сначала стандартная функция geid и стандартная переменная IE. Затем описываются главные глобальные переменные и определяются их значения. Тут я должен сказать, что символ $ допустимо использовать только в Javascript, в HTML коде это не разрешается. Поэтому во всех значениях параметров id стоят нули вместо доллара. При наложении двух анимаций надо будет сделать две копии кода, в первой заменить символ $ на 0, а во второй -- на 1. Затем во второй копии вручную надо будет заменить 0 на 1 в значениях параметров id. Сначала мы определяем указатели на пареметры style наших областей и картинок. Затем внутри функции init$ определяем фактически входные данные для анимации. Только в этой функции надо будет что-то менять при создании новой анимации из старой. Здесь задаются два глобальных массива текстов, первый массив для интернет адресов картинок, второй массив для записи текстом параметров перехода для каждой картинки. Задавая параметры перехода для каждой картинки мы имеем полную свободу задавать индивидуальный переход для каждой картинки. Если это не требуется то массив можно определить автоматически в цикле. Можно в явном виде указать все URL адреса и все числовые значения для параметров. Но можно использовать вспомогательные переменные для повторяющихся кусков текста или глобальные переменные для записи повторяющихся значений. Вспомогательные тексты могут быть определены локально, а к переменным должен быть доступ при считывании данных.

В данном примере используется всего 5 картинок, все они находятся в одной папке на сервере. Поэтому использование дополнительных локальных переменных позволяет сократить запись адресов картинок. Что касается параметров, то среди значений есть одинаковые и разумно их записать в перемнные. К тому же эти переменные легко изменять. Смысл переменных такой: p$ -- время показа одного кадра в миллисекундах, w$ и h$ -- ширина и высота окна показа. В данном примере размеры картинок не фиксируются, они могут быть любые. Параметр im$ указывает полное число картинок для показа. Формально оно должно совпадать с размерами массивов. Но я сделал проверку и если оно превышает минимальный размер из двух, то оно уменьшается до минимального размера. А если меньше, то просто в анимации будут участвовать не все элементы массива. Здесь же заданы стартовые значения для уже описанных переменных ona$, key$, dir$, nex$. Смысл параметров переходов пока не ясен, я буду описывать их в постоянной части. Просто скажу еще, что переменная i$ -- это счетчик кадров. Итак с этим куском все. Перейдем ко второму куску
В этом коде записана первая часть универсальной функции move$(). Функция имеет набор глобальных переменных, это все те, которые оканчиваются на символ $, и имеет некоторые локальные переменные. Так вот локальные переменные описаны в декларации var список переменных, а глобальные не описаны. На самом деле в javascript не обязательно описывать переменные, они определяются в момент первого присвоения им значения. И являются глобальными. Однако если их описать в теле функции, то они будут локальными. Наша проблема в том, что локальные переменные не выходят за пределы тела функции и их не обязательно делать разными. А глобальные в разных функциях должны быть разными. Поэтому они все имеют знак $ на конце. Итак все тело функции помещено в условное выражение и если ona$=false, то ничего не происходит, анимация стоит. Таким образом, если по кнопке менять значение этой переменной в специальной функции, то все будет работать. У нас стартовое значение ona$=true.

Далее, все тело функции разбивается на две части, как я уже писал. В данном коде представлена первая, установочная часть. Она выполняется если key$=true, как у нас и есть исходно. Но внутри этого куска, код key$=false; pause=0; делает так, что после выхода функция будет запущена снова с минимальной отсрочкой и пойдет во второй кусок, то есть в часть перехода. Далее по значению переменной dir$ счетчик картинок либо увеличивается га единицу, либо уменьшается. Соответственно определяется номер нижней (предыдущей) картинки. После того, как счетчик задан, берется соответсвующая строка массива параметров, разделяется на массив строк по знаку запятой, и их каждого куска берется число. Это делает функция eval(), которую я описывал в примере Калькулятор (статья 3.1). В результате мы имеем массив par[ ] числовых значений параметров. Теперь можно поговорить об их смысле. par[0] -- время показа данного кадра после перехода, par[1],par[2] -- x,y конечные координаты движущейся картинки, par[3] -- число кадров перехода, par[4],par[5] -- начальные координаты движущейся картинки, par[6] -- время показа одного кадра перехода, par[7] -- код перехода (kt$).

Такой смысл имеют параметры по коду перехода kt$=0. Этот код перехода описывает 8 переходов с движением картинки. На самом деле можно сделать больше переходов и показывать только часть картинки, но 8 -- это основные. Переход реализуется за счет движения области рамы (obj$) Остальные области и картинки в них стоят на месте, они как бы избыточны. Невидимость лишнего реализуется за счет основного окна (mww$). Переходы типа выталкивания имеют kt$=1. В этом случае рама стоит на месте, новая картинка двигается внутри рамы, старая картинки тоже двигается со сдвигом на размер основного окна. Код так написан, что координаты самих картинок никогда не меняются, двигаются области в которых они сидят. Поэтому я буду говорить о нижгней и верхней картинках имея в виду их области, а верхняя картинка дополнительно имеет раму, ограничивающую ее видимость.

Следующие 8 переходов, когда обе картинки стоят неподвижно, а меняются размеры окна рамы, ограничивающей видимость верхней картинки реализуются при kt$ от 2 до 9, каждый переход при своем значении переменной kt$. Тут нижняя картинка стоит, меняются размеры и положение рамы (obj$) и так как внешняя картинка (img$) задана относительно рамы, то для того, чтобы она оставалась на месте, ее координаты тоже должны изменяться синхроннно с изменением рамы. Расчеты приходится делать раздельно для каждого перехода. Я не буду детально описывать эту математику, кому интересно -- разбирайте код, он правильно все делает. Переходы с развертыванием и схлопыванием картинок реализуются при kt$=10,11. Развертывание делается аналогично, только другой алгоритм подсчета координат и размеров, а вот для схлопывания приходится новую картинку помещать вниз, а старую наверх, то есть менять картинки местами. И затем проделывать уменьшение размеров рамы до нуля фактически со старой картинкой. А новая при этом открывается, будучи в нижнем слое.

Наконец, при kt$=12 старая картинка стоит, рама имеет конечные размеры и тоже стоит, а внутри нее двигается верхняя картинка. При этом меняется только часть полного окна анимации внутри рамы, размеры которой могут быть меньше окна. Возможно я неправильно называю рамой фактически щель (апертуру). Но рама -- это тоже щель, она может показывать картинку не целиком, а частично. Наконец, при kt$=13 делается переход с изменением прозрачности. Этот переход я описывал в отдельном примере. Здесь он является частью мультиперехода. В самом конце показанного кода внутрь параграфа записывается текст с номером текущего кадра и времени его показа в секундах. Пора показывать остальную часть кода функции
Итак в этой второй части, описывающей переход стоит условие на счет кадров перехода. Исходно в первой части в переменной nm$ определяется полное число кадров перехода и обнуляется счетчик кадров n$. Соответственно функция много раз попадает сюда, пока не выполнит весь переход. При этом время задкржки устанавливается на время, записанное на один кадр перехода, это десятки миллисекунд, но для компьютера это огромное время. Далее в зависимости от типа перехода выполняются соответствующие расчеты координат и размеров областей, я не буду подробно описывать как это делается, математика тут на уровне арифметики для школьников пятого класса. Наконей наступит момент когда переход закончится. А теперь вроде бы надо просто ждать большую паузу равную времени показа кадра. Не все так просто. Мы ведь хотим иметь возможность по кнопке прервать показ и принудительно перейти к следующему кадру. Для этого полное время показа разбивается на 200, и 200 раз в течение этого времени проверяется значение параметра nex$. Если оно false, то просто двигает счетчик и по окончании цикла мгновенно возвращаем программу в первую часть. А если оно true, то делаем его false и тоже мгновенно возвращаем в первую часть, не дожидаясь окончания цикла. Вот и все тело функции. А в конце стоит вызов этой же функции через новое время. Эта функция и реализует все наши сложные циклы, описанные выше. Осталось только запустить обе описанные функции и дело сделано.

О том как реализовать кнопки, масштабирование картинок, сделать полномасштабную программу анимации, которая легко настраивается на любой набор картинок, я расскажу в другой статье. Важно, что описанная функция move$() может быть основой очень большого числа самых разных слайд-шоу. Но и это еще не предел, можно реализовать больше переходов и другие переходы. Но общий принцип останется тот же.

Автор: Виктор Кон,   перейти На главную

 

счетчик посещений
free hit counter
free hit counter
Сайт создан в системе uCoz