css, html, php, javascript, jQuery, ajax … – решения, примеры, рецепты
19 Мар
Собственно я не собирался делать вообще никаких галерей. Просто как обычно отметил для себя довольно часто повторяющийся вопрос – как заставить картинку плавно появиться после ее окончательной загрузки? В общем это не очень сложно, но чтобы придать примеру какую-то практическую пользу я покажу как сделать из этого простенькую мини фотогалерею. Основное ее достоинство в том, что она реализована всего одиннадцатью строками кода, но думаю многим сможет пригодиться, поскольку не всегда бывает нужна мощная функциональность таких галерей как LightBox или FancyBox.
Начинаем с само собой разумеющегося – подключаем библиотеку jQuery:
<script src="js/jquery-1.3.1.js" type="text/javascript"></script>
Постараемся не вносить в HTML-разметку лишних идентификаторов, имен классов, попробуем обойтись минимумом. Для выстраивания миниатюр используем ненумерованный список ul, в каждом элементе li которого и будет содержаться миниатюра. Миниатюре – тэгу img, добавим атрибут alt, в который напишем комментарий к фотографии. Картинку-миниатюру заключим в тэг a, атрибут href которого будет указывать на полноразмерную фотографию. С миниатюрами все. Добавим в HTML-разметку элемент div, в который будем загружать полноразмерные изображения при клике на соответствующую миниатюру и вот ему пожалуй придется присвоить идентификатор #imgHolder. Получилась вот такая простенькая разметка:
<ul>
<li>
<a href="max/1.jpg">
<img src="min/1.jpg" alt="Офигительный жучила..." />
</a>
</li>
.......
<li>
<a href="max/7.jpg">
<img src="min/7.jpg" alt="Гадина какая-то страшная..." />
</a>
</li>
</ul>
<div id="imgHolder"></div>
С помощью CSS оформляем разметку так, как нам понравится.
img { border:none; }
ul { margin:0; padding:0; list-style:none; }
ul li { display:inline; }
#imgHolder {
position:relative;
width:800px; height:600px;
overflow:hidden;
}
#imgHolder em {
position:absolute;
left:10px; bottom:10px;
margin:2px 10px; padding:2px 10px;
background-color:#000; color:#fff;
}
В примере – не показываем рамку у изображений, для списка задаем нулевые значения полей и отступов, для элементов li устанавливаем свойству display значение inline, вытягивая таким образом список в строку. Зададим блоку #imgHolder ширину, высоту и на всякий случай свойству overflow присвоим значение hidden. Позиционируем элемент em внутри div‘а абсолютно (сюда будем выводить комментарии к фотографиям) и оформим его соответствующим образом.
Осталось самое главное – эти одиннадцать строк кода, которые заставят работать эту конструкцию. Вот эти строки:
$('ul img').click(function(){
var path = $(this).parent().attr('href');
var alt = $(this).attr('alt');
$('#imgHolder').animate({opacity: 0},1000,function(){
$(this).html('<img src=' + path + ' />').find('img').bind('load',function(){
$(this).parent().append('<em>' + alt + '</em>').animate({opacity: 1},1000);
});
});
return false;
});
$('ul img:first').click();
Давайте подробно, строка за строкой разберемся, что мы тут наделали.
При загрузке страницы, вернее при наступлении момента готовности DOM (кусок кода с $(document).ready() опущен) мы выбираем все элементы img, которые являются потомками элементов ul. Есть у нас такие? Да, есть – это картинки-миниатюры. Связываем с этим набором элементов событие click, при наступлении которого выполним некоторую функцию.
Что же будет делать эта функция? Для начала определяем пару переменных. path – здесь мы запомним значение атрибута href элемента, который является предком картинки-миниатюры, т.е. элемента a. alt – сюда поместим содержимое атрибута alt самой картинки-миниатюры, чтобы впоследствии вывести его в качестве комментария к полноразмерному изображению.
Дальше начинается самое интересное – с помощью метода animate() мы в течение 1000 мс плавно скроем элемент div с идентификатором #imgHolder через задание значения 0 его CSS-свойству opacity. И как только это произойдет начнем действовать дальше, указав в третьем параметре метода animate() callback-функцию, которая будет вызвана в этот момент.
Внутри этой функции this ссылается на элемент div с идентификатором #imgHolder. Помня это обстоятельство, помещаем в этот элемент div фрагмент html-кода, описывающий элемент img – полноразмерную картинку. В атрибуте src которой указываем путь, сохраненный ранее в переменной path. Следуя далее по цепочке вызовов, отыскиваем только что добавленный элемент с помощью метода find() и используя метод bind(), связываем еще одну callback-функцию c событием load – с моментом загрузки полноразмерного изображения.
Внутри этой функции this указывает уже на большую картинку, поэтому мы отыскиваем ее родителя (элемент div #imgHolder) и используя append() добавляем туда em с комментарием, который предусмотрительно сохранили в переменной alt. После этого вновь используем метод animate(), но уже для того, чтобы плавно, в течение 1 секунды показать элемент div #imgHolder с уже загруженной полноразмерной фотографией, устанавливая CSS-свойству opacity значение 1.
return false служит для того, чтобы предотвратить стандартные действия браузера (т.е. переход по ссылке) при клике на элементе a.
Осталась только самая последняя строка кода, которая служит для того, чтобы при загрузке страницы подгрузить в #imgHolder полноразмерную фотографию с помощью эмуляции события click на первой картинке-миниатюре.
Проверил и убедился, что все работает в в FF2 и 3, Opera9, IE6 и 7, Google Chrome.
Вы можете открыть пример в новом окне, испытать его и посмотреть полный исходный код. Вы можете скачать архив, который содержит все файлы примера.
Предупреждая вопросы насчет всяких стрелочек вперед – назад и прочих штучек, хочу сразу напомнить, что это всего лишь пример, с помощью которого я стараюсь объяснить, как плавно скрыть и не менее плавно показать большую картинку только после ее окончательной загрузки.
Отзывов (57) на «Мини фотогалерея из 11 строк кода»
Спасибо, просто и доступно (-:
Не в качестве критики: стоит ещё сделать предварительную загрузку изображений, но, думаю, это уже выходит за рамки задуманной статьи (-:
Логика ясна, теперь я более четко представляю как работает call-back )))
Вы гений
Чем же это я Вам так помог-то?
Gennady подскажите пожалуйста, вот есть несколько картинок как отследить загрузку их всех, а уж потом вызвать нужную функцию
З.Ы. мое знакомство с jquery начинал с вашего сайта, заранее спасибо за все
Сразу скажу – сам не пробовал, но теоретически должно сработать. Попробуйте отобрать в селекторе jQuery все нужные изображения (по имени класса или вообще по img) и подцепить к этому набору событие. Так примерно:
$('img').bind('load', function(){ ... });Напишите тогда, получилось или нет…
Хотя засомневался я что-то. Надо тоже попробовать – не будет ли callback-функция вызываться для каждого элемента в наборе?
если я правильно понял, вот так:
$(‘.img1′).bind(‘load’, function(){
alert(1);
});
алерт выскакивает по загрузке каждой картинки, а надо что бы когда все, а потом алерт (нужная функция)
урезались картинки
img src=»1.jpg» class=»img1″
img src=»2.jpg» class=»img1″
img src=»3.jpg» class=»img1″
Да-да, я тоже уже попробовал… Срабатывает для всех. Ну да выход-то всегда придумается. Сейчас попробую.
Можно так:
var n = $('img').length-1; $('img').each(function(i){ $(this).bind('load',function(){ if(i == n) alert('Готово!'); }); });Пересчитываем нужные картинки и пользуясь тем, что вспомогательная функция each() может принимать параметром индекс элемента в наборе, проверяем для каждого элемента условие i == n. Если оно выполнится – только тогда вызываем функцию.
большое спасибо! это оно
но вот что я заметил, если картинкам прописать display:none; то в опере не происходит
alert(‘Готово!’);
тоэтому я прописал
position:absolute;visibility:hidden;
а как прикрурить прелоадер большого изображения?
или иконку загрузки
Вернемся к началу статьи – я не делал галерею, я старался пояснить механизм отслеживания момента загрузки изображения, чтобы по этому событию что-либо выполнить. Только и всего.
В принципе мне в ближайшее время и самому понадобится делать что-то похожее. Сделаю – конечно же выложу.
А есть возможность сделать фотогаллерею из превьюшек, но при наведении на фото или картинку она бы увеличивалась!?
Сделано исключительно на CSS – http://www.linkexchanger.su/2008/63.html
либо смотрите LightBox или FancyBox.
Подробное описание и инструкции плагина Lightbox – http://itforweb.com/content/e137/
у ВП есть плагин, который помогает выводить код на странице
Есть конечно. Я использую CodeHighlighter, но он не всегда помогает….
больше всего мне понравились комментарии первой и последней фотки в примере)).. и ещё, для такой маааленькой галереи жалко подгружать 100кб библиотеки jquery
сделайте плз в прелоадом
Даже не 100, а 120 кБ. Но это версия для разработчиков. На самом деле можно было бы обойтись файлом всего в 19 кБ.
И потом, не только же для одной галереи библиотека подключается – много чего еще полезного можно сделать…
Здравствуйте, на основе этой статьи, я хочу сделать фотогалерею, но в скрипте задействованы ul и li теги, а возможно без них? Чтобы функция определяла куртинку, например, по id?
Все возможно – в примере функция связана со всеми элементами img, которые являются наследниками списка. А Вам нужно описать в селекторе правило, которое отберет в набор нужные Вам элементы. По id, так по id – в селекторе можно указывать их через запятую….
Спасибо Вам большое! Все работает.
Вот есть такой код в хтмлке:
И есть php файл который выводит результат в жаба скрипт:
echo «document.writeln(‘‘)»
Подскажи, чем заменять кавычки внутри функции эхо?
блин, ворд пресс ява код не дает вставить.
короче стандартный вызов пчп файла при помощи функции «скрипт»
пчп выполняется и передает назад скрипту «документ.врайт»
Ну вот собственно проблема у меня с кавычками.
Наверника ты знаешь как она решается.
помоги плиз.
Кавычки подрубаются обратным слешем….
Gennady, спасибо.. А то пхп все кровь выпил.
- а нельзя каким либо образом заменить картинки-превьюшки обычными текстовыми ссылками?
- тоесть чтобы клик по текстовой ссылке приводил к смене основного изображения.
За раннее спасибо!
Можно конечно, почему нет? Только сейчас примера кода от меня не ждите – я в отпуске, на связь выхожу на часок в сутки всего, а дел много. Так что после 22 июля…
Можно ли обновить картинку средствами jquery? При условии что название файда не меняется.
Не очень вопрос ясен, но попробую угадать – наверное пытаетесь использовать GET-запрос и столкнулись с обычным кешированием. Добавьте в запрос случайный параметр и тогда картинка будет подгружаться обновленная.
Уж не знаю, на тот ли вопрос ответил…
И всетаки:
- а нельзя каким либо образом заменить картинки-превьюшки обычными текстовыми ссылками?
- тоесть чтобы клик по текстовой ссылке приводил к смене основного изображения.
Допустим для использования в каталоге продукции.
За раннее спасибо!
А не подскажете, что нужно/можно добавить, чтобы по клику увеличенной картинки она закрывалась?
Подскажу TINA,
добавить нужно это:
$('#imgHolder img').live('click', function(){ $(this).parent() .find('em') .remove() .end() .animate({opacity: 0},1000); });Может быть можно и попроще, но это первое, что пришло в голову…
Игорь, если html-разметку приведете к такому виду:
<li><a href=»max/2.jpg»>Как кошка с собакой?</a></li>
<li><a href=»max/3.jpg»>Птичка</li>
то весь код можно будет так записать:
$('ul a').click(function(){ var path = $(this).attr('href'); var title = $(this).text(); $('#imgHolder') .animate({opacity: 0},1000,function(){ $(this).html('<img src=' + path + ' />') .find('img').bind('load',function(){ $(this).parent() .append('<em>' + title + '</em>') .animate({opacity: 1},1000); }); }); return false; }); $('ul a:first').click();Gennady, спб вам большое!!
Gennady, Спаибо за помощь!
Здравствуйте, у меня такая проблема, вставил код, но при нажатие на какую-либо картинку она открывается большой в новом окне. Что я сделал не так?
Скорее всего не подключена библиотека. Первое – проверить пути…
В опере 10 не хочет срабатывать событие load, или не происходит бинд …
(‘img’).bind(‘load’,function(){// код не выполняется})
или срабатывает както через раз…
Хм, да есть такой интересный момент – специально десятую Оперу поставил. На 9-ой все в норме было. А тут работает, но только первый раз. Когда начинаешь идти по второму разу по картинкам – они уже не отображаются….
Интересненько… Будем подумать…
День добрый специалисты.
Подскажите пожалуйста сложен ли код такой галереи http://saydanke.ru/photoimperia/photo&id=0
?
Можно ли организовать такое в HTML? Или необходима поддержка PHP? (и вообще правильно ли я спросил?
Заранее не ругайте и спасибо.
Это LightBox.
Спасибо.
Да, отличный сайт, спасибо за такую информацию..раньше думал что пришлось бы прописывать сотни строк, что бы сделать нечто подобное.
Добрый день. Gennady у меня есть такой вопрос:
есть изображение больших размеров, и при загрузке страницы они сильно затормаживают загрузку… как можно с помощью jQuery сделать так, чтоб бы до загрузки изображение – они не выводились на страницу. а выводились (показывались) после – когда изображение полностью будут загружены. Я попытался реализовать данную схему с помощью load – но у меня не получилось. Не подскажите как можно решить данную задачу.
Заранее спасибо!
Артур, почему не получилось? Должно получиться! Собственно как это сделать в статье написано, но давайте еще раз:
Картинка наверняка имеет элемент-родитель? Скройте его при инициализации. С картинкой связывайте обработчик load, который будет показывать картинку, когда она загрузится полностью.
Но внимание! Картинка, которая подгружается из кэша, в Opera 10 (пока только в нем наблюдал) не вызывает load почему-то, так что тут надо будет подумать…
З.Ы. Об этом выше писал Kostya.
Добрый день, Gennady.
Использовал похожую схему для организации галлереи… И вот 10-ая опера подложила мне свинью. Пришлось походить по старым сайтам и временно «загрубить» срабатывание алгоритма для Оперы.
Проблему пока решить не удалось.
Есть подозрение, что load все же срабатывает (ну должно же), но функция реакции на это событие устанавливается чуть позже чем происходит загрузка изображения…
Добрый день jakov!
Я могу пояснить причину, ибо разбирался с этим
load то срабатывает, то нет (причем не только в 10-й Опере – при небольшом весе картинок можно «добиться» того же и в других браузерах). Причина в кэшировании картинок браузерами. Пока в кэше картинок нет – все работает прекрасно. Как только картинка начинает подгружаться из кэша – возможны варианты….. Успеет код сработать раньше того, как подгрузилась картинка, значит все будет нормально, не успеет, значит никакого load и не будет.
Решение через ж…. в общем лежит на поверхности – добавить в url картинки случайный параметр. Но конечно ни о какой экономии траффика в этом случае речь не идет. В общем это такое «пожарное» решение.
может расскажете как сделать кнопочки вперед назад? а то я что то туплю не могу сообразить как сделать переменную отвечающую за имя
Ну, это всего лишь простой пример, демонстрирующий принципы, а не фотогалерея как таковая….
Может быть Вам лучше использовать готовый плагин?
Например этот:
http://coffeescripter.com/code/ad-gallery/
спасибо именно это мне и было нужно
Gennady приветствую!
1)все хорошо для примера но подскажите новичку как с оперой решить вопрос, как правильно подставить случайные парамметры.
2) как предвратительно загрузить эти картинки?
Спасибо за ваш блог
Сергей
Здравствуйте Сергей!
Эта статья демонстрирует принципы, но в качестве нормальной галереи такого плана, лучше все-таки использовать полноценный плагин.
Посмотрите этот http://coffeescripter.com/code/ad-gallery/
Здравствуйте.
Спасибо большое за отличный пример.
Подскажите, пожалуйста, как сделать так, чтобы можно было использовать несколько таких мини-галерей на одной странице, чтобы они были независимы между собой.
С уважением.
Просто сделать несколько разных списков в html-разметке… Ну и разве немного подправить селектор, по которому все это выбирается. Просто надо немного почитать про селекторы jQuery и все станет очень понятно.
Оставьте отзыв