| Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате |
| Форум программистов > JavaScript: Общие вопросы > Прелоад картинок средствами js! |
| Автор: Frantishik 26.5.2008, 20:44 |
| Люди помогите...... Хочу сделать предзагрузку картинок на js, т.е что б тело сайта не отображалось до тех пор пока все картинки не загружены? вешал на onload функцию function preload(){ if (document.images) { preload_image_object = new Image(); // set image url image_url = new Array(); image_url[0] = "assets/images/adress.gif"; image_url[1] = "assets/images/logo.gif"; .............................................................. var i = 0; for(i=0; i<=10; i++) preload_image_object.src = image_url[i]; } } не подгружает... вешал скрипт в head...то же не помагает для чего надо? см.: http://frant.site88.net/ |
| Автор: bars80080 27.5.2008, 09:13 | ||
мож их по массиву загрузить?
|
| Автор: Ghirik 27.5.2008, 14:31 |
| Где то здесь предлогали использовать динамическое создание объекта Image, примерно такое же название темы было. Т.е. через createElement и appendChild... |
| Автор: Frantishik 29.5.2008, 13:12 |
| bars80080, пробовал .... так как не работает упростил код.... я думаю идея такая,нужно в цикле проверять загруженность картинок. у обьекта image есть свойтсво complete. вот только при проверке ие ведёт себя непредсказуемо. нигде не могу найти чёткий пример с кроссбраузеностью... |
| Автор: Ghirik 29.5.2008, 14:00 |
| http://door-to.ru/LamerPhotoBlog/scripts/slideShow.htm Там только код шибко криво форматирован... Ну, меня тогда ещё не научили... |
| Автор: IDVsbruck 29.5.2008, 14:16 |
| Тут не должно быть проблем с кроссбраузерностью - все в пределах синтаксиса js, а событие onload у image работает давно и везде. Можно пойти по следующему пути: 1. Грузим флеш, анимашку или просто картинку, типа "страница грузится". Вешаем на ее загрузку onload (для флешки/object тоже подойдет). 2. При вызове обработчика события загрузки запускаем таймер-интервал, к примеру, на 1 секунду и создаем все элементы createElement("img"). На каждый вешаем событие onload. 3. В функции, вызываемой таймером, проверяем (по выбору): а) флаг для каждой картинки; б) количество загруженных картинок. 4. При достижении финала загрузки картинок прекращаем вызов функции по таймеру и отображаем страницу (глобальный div, innerHTML для body, подгрузка AJAXом). Никаких проблем с разными браузерами быть не должно. |
| Автор: Ghirik 29.5.2008, 15:13 |
| IDVsbruck, и зачем это всё? таймеры и прочее... по моей ссылке, что, предзагрузка не происходит? Добавлено через 22 секунды Или не кроссбраузерно? |
| Автор: IDVsbruck 29.5.2008, 15:22 |
| Не, по твоей не происходит ... сначала вижу текст страницы, а потом начинают появляться картинки (я про ИЕ, т.к. в ФФ отображение идет одновременно). Вот вопрос: "Хочу сделать предзагрузку картинок на js, т.е что б тело сайта не отображалось до тех пор пока все картинки не загружены?" Ответ: Надо сначала все загрузить, а потом все отобразить. Я предложил свой вариант. |
| Автор: Ghirik 29.5.2008, 15:38 |
| Дак, это разве проблема? Сложность как раз в контроле загрузки картинок, а показать и скрыть body, даже я смогу. |
| Автор: Frantishik 29.5.2008, 18:25 |
| вот и я про это..... нужно выловить событие когда загрузка картинки завершенна.... |
| Автор: Ghirik 29.5.2008, 18:34 | ||||
Frantishik, http://door-to.ru/LamerPhotoBlog/scripts/slideShow.htm Там же всё ловится, во всех браузерах... показ картинок начинается только после полной загрузки всех. Добавлено @ 18:41 Вот всё что вам нужно.
И bars80080 об этом же говорил... Вы пробовали? |
| Автор: Frantishik 29.5.2008, 18:50 | ||||
| Ghirik, дело в том что просто при создании объекта картинка не грузится,
Зесь по сути то же самое что и у меня, только создаётся обьект Image....
|
| Автор: Ghirik 29.5.2008, 19:05 | ||||
Ну... Ни чего себе! то же самое.... Если Вы говорите про это:
То это, конечно, не будет работать... буквы не правильные... |
| Автор: SelenIT 29.5.2008, 19:05 | ||
Frantishik, у Вас создается один объект Image. И вы говорите ему буквально следующее:
А в коде Ghirikа свой объект Image создается для каждой картинки, которую нужно загрузить - и, если не произойдет ничего непредвиденного, дожидается ее загрузки. А на случай непредвиденности нужно предусмотреть таймер, чтобы, если картинка не загрузилась, скажем, через 15 сек. - отобразить вместо нее див с извинительным текстом. А то при такой постановке задачи одна недогрузившаяся картинка намертво заблокирует всю страницу... |
| Автор: Ghirik 29.5.2008, 19:14 | ||
Точно, я как то об этом не думал.... Опыту нету, однако.... |
| Автор: IDVsbruck 29.5.2008, 22:26 | ||
Чего-то непонятное вы тут развели ... совсем в дебри зашли.
Понятно, что две последние функции - это спрятать сообщение о загрузке и открытие всей странички. Во избежание проблем с последующим вызовом функции-проверки загрузки картинки событие onload обнуляем. id использовал для возможного последующего использования с помощью DOM. Однако это необязательно: просто когда открывается тело страницы, там стоят ссылки на те же картинки, которые мы грузили, браузер проверяет наличие их в кэше (а они там уже есть), сверяется по размеру с сервером и показывает их ... это уже будет происходить почти мгновенно. Другое дело, что если действительно хотя бы одной картинки не будет на сервере или где-то закрадется ошибка, то вся страница так и не покажется. Это действительно можно решить с помощью функции, вызываемой таймером, через достаточно длительное время 15-30 секунд, которая в любом случае откроет страницу. Тут вариантов для размышления много: подстановка картинки-ожидалки, изменение всего окна, ajax-запрос с "выяснением судьбы" картинки на сервере с последующим отображением. Одним словом, тему можно развивать в этом направлении до полного абсурда |
| Автор: Ghirik 30.5.2008, 05:11 | ||
| IDVsbruck, а в работе этот код нельзя посмотреть? А то вы только кусочек привели... А где оно аппендчилдица? И если не трудно, смысл этой строчки объясните:
Я понимаю, что она означает "хрен вам, а не оработчик" От хтмл до хтмл нарисовали бы, а то я сейчас обнаружил, что метод, используемый мной не хочет работать в IE6. Вернее, по ссылке, которую я приводил, он работает, а отдельно загрузка через создание new Image не хочет в IE6... |
| Автор: Ghirik 30.5.2008, 09:06 |
| Блин, чего то сморозил... Видимо не проснулся ещё... Но все равно посмотреть бы на работающий пример... А то у IE своё особенное отношение к событию onload. Добавлено через 3 минуты и 12 секунд В IE должен правильно работать readyState... |
| Автор: IDVsbruck 30.5.2008, 12:51 |
| У меня нет от <html> до </html> ... это я тут накропал. Но код должен быть на 95% работающий. Просто часто приходится сталкиваться с загрузками/подгрузками и т.д. - проекты в основном динамические и на ajax'е построены. Да вроде все привел. Просто в последние функции вставить что надо, тем более, что "а показать и скрыть body, даже я смогу" (с) ... createElement сдужит не для отображения, а просто, чтобы подхватить картинку с сервера. Если не нравится, что память замусорена, то их перед отображением боди можно удалить. Суть в том, как работает механизм загрузки картинок: если раз была загружена в кеш, то второй раз уже берется из него, а не подгружается. |
| Автор: Ghirik 30.5.2008, 14:05 | ||
Нет, ну что код не будет работать, это точно. Кроме того, что создать элемент методом createElement, нужно его ещё и в дерево поместить, т.е. добавить appendChild. Счас проверю, как он поведет себя в IE6.... Добавлено через 7 минут и 15 секунд А всё же, ято означает эта сточка? document.getElementById(image_id).onload = null; Я первый раз такое вижу, зачем? Чего боимся? |
| Автор: Ghirik 30.5.2008, 15:35 | ||
| Да, действительно onload у img работает исправно во всех браузерах. А то я что то сомневался... у боди в IE6 onload настыпает если даже ещё не загружены картинки в массив. Да и у фрейма onload не работает в IE6. http://door-to.ru/scripts/preload_img.htm
Использовать скрытие боди не стал, не всегда это удобно. |
| Автор: IDVsbruck 30.5.2008, 16:45 | ||||||
| Ghirik, извини, но ты не понял моей идеи, которую я, в принципе, не очень стал комментировать. Не надо ничего делать с созданными картинками: ты же не знаешь, куда именно они поместятся - в бекграунд, див, таблицу и т.д. А может, среди них есть пока скрытый анимационный гиф, который показать надо в каком-то определенном месте? Не надо ничего накапливать, чтобы потом пытаться вставить ... Есть постановка задачи: есть страничка (простая или сложная - нам все равно), которую надо показать только после того, как загрузятся все имиджи. Может, она получена асинхронно с сервера? Вот пусть она и остается страничкой. В своем скрипте я просто делаю прелоадер картинок с сервера на клиента, а не в страничку (!!!). Когда загрузили все, открываем страничку, в которой ссылки на картинки остались прежними - с сорсами на относительном пути как они лежат на сервере. Просто работа загрузки картинок так работает, что когда клиент снова сталкивается с картинкой (которую мы только что подгрузили), то проверяет ее наличие у себя в кеше ... а мы знаем, что только что ее туда загрузили. Поэтому она будет показываться практически мгновенно (в принципе, практически незаметно для глаза). Я проверил свой код. Все-таки я не ошибся и он на 100% рабочий. Я понимаю, что смущает постоянное переопределение переменной, которой присваивается элемент имиджа и заново дается событие и т.д. Конечно, выглядит абсурдно, но javascript настолько гибок, что данная вещь работает. Причем, каждая картинка вызовет именно свой обработчик, со своим указанным id. Насчет строчки document.getElementById(image_id).onload = null; ... По неизвестной мне причине при последующей загрузке картинок почему-то бывает сбой и картинка снова качается (типа no-cash для нее срабатывает). Получается, что если мы все же будем использовать созданные элементы в странице (по id или посредством DOM), то возможно повторное скачивание картинки. Поэтому, чтобы не допустить повторного вызова обработчика, мы его переопределяем. Как говорится ... лучше перебздеть, чем недобздеть. Это я как бы в своем коде сразу поставил блоки против неправильной работы ... мне все равно, а тому, кто будет использовать, будет небольно. И все же считаю, что мой код в силу использования абсурдных фич js намного элегантней ... Единственное, его даже можно оптимизировать:
Причем, это тот же код, что и делался раньше
Добавлено через 14 минут и 52 секунды Да, кстати ... твой код
должен либо выкидывать эксепшн (в ИЕ будет желтый треугольничек внизу), либы добавлять к боди лишний элемент типа undefined. Объясняю: пусть img_max = 2, выражение while (i--) возьмет значение 2, сверит его с 0, а лишь затем вычтет единицу. А imgs[2] у нас нет, и равно undefined. Значит, пройдет 3 значения: imgs[2], imgs[1], imgs[0]. Чтобы у тебя работало, должно быть while (--i) document.getElementsByTagName('body')[0].appendChild(imgs[i]); Кстати, подобная аналогия с for (var i = 0; i < 10; i++): первым идет i=0, а не 1 (i++). Хотя это исключительно теоретическая платформа, проверять на практике лень - чем черт не шутит, возможно, по неизвестной мне причине будет работать. В этом случае приношу извинения. |
| Автор: Ghirik 30.5.2008, 18:52 | ||
Ну, Вы добавьте ещё восемь картинок и вывод на страницу, а уже потом рассматривайте элегантность... Это всё мелочи, и while вроде нормально работает, просто он нулевую картинку не берет, я подумал ну и пусть, зато элегантнее. Использовать таймаут у меня рука не поднимается, но пока решения не вижу.... |
| Автор: Ghirik 30.5.2008, 19:10 |
| Тьфу, блин! как я про complete то забыл... счас проверку устрою... |
| Автор: Ghirik 30.5.2008, 19:28 | ||
Вот анекдот то! Сделал так.
http://door-to.ru/scripts/preload_img_bad_IE6.htm IE6 совершенно странно Добавлено через 4 минуты и 23 секунды Ни чего не понимаю... сейчас нормально стало открываться... А до того как написал предыдущий пост, открывались не все картинки. При том каждый раз - разное количество.... Добавлено через 6 минут и 24 секунды Какой то глюк был... Сейчас всё нормально. Пошел исправлять выложенный код. Добавлено через 13 минут и 34 секунды Во!!!, теперь снова глючит.... |
| Автор: Ghirik 30.5.2008, 19:46 |
| Не успевает он, что ли, проверить наличие файла в кэше.... |
| Автор: IDVsbruck 30.5.2008, 19:51 |
| Да хоть 88! Какая разница? Зачем еще несколько циклов?? - Я так понимаю, что мои объяснения или не приняты, или не дошли ... Код совершенно рабочий для ЛЮБОГО количества картинок. С кешированными картинками пришлось задуматься минут на 10 ... но решение вполне доступное и простое. Более того, мы все им пользуемся достаточно часто. Надо генерировать случайное число/строку и добавлять к src: preload_image.setAttribute("src", image_urls[i] + "?rand=" + random_variable) - так картинки будут грузиться гарантийно каждый раз. Но так мы постепенно подходим к главному вопросу: а зачем это делать, если это не облегшает и улучшает работу, а наоборот? |
| Автор: Ghirik 30.5.2008, 20:34 | ||||
Я считал, что задача стояла задержать отображение до полной загрузки картинок. Так вроде автор темы просил... Или он просил научить складывать картинки в кэш? Что толку от загруженных в кэш картинок, без правильного механизма их вывода на экран, без правильно полученного события окончания загрузки. Мой код практически ни чем не отличается от предлагаемого вами. Как мой код не работал качественно, так в точности и ваш. По своему коду я вот такое решение нашел, я о readyState уже писал, он правильно работает.
Сейчас попробую и ваше.... Добавлено через 10 минут и 36 секунд imgs[i].readyState == "complete" тоже через раз работает.... Добавлено через 13 минут и 31 секунду preload_image.setAttribute("src", image_urls[i] + "?rand=" + random_variable) - с родни шаманству, даже проверять не стану. Нужно у браузера узнавать, есть ли у него такая картинка. А если шаманить, то тогда можно и на серере это решить.... |
| Автор: IDVsbruck 30.5.2008, 20:49 |
| Я выпадаю из спора, так как считаю, что мы движемся по разным, но параллельным, путям к решению задачи. А наши решения, похоже, кроме нас самих никому не интересны Просто на страницах форума я никогда не решаю задачи от <html> до </html> - неинтересно, да и не хочется. Да и проверять код не хочу - жалко времени и лень. Считаю, что автор топика в любом случае сможет составить какое-то решение, основываясь на наших постах. Рад общению и спору. |
| Автор: Ghirik 30.5.2008, 21:11 | ||||
Спасибо за компанию. Я выяснил причину. Оказалось IE6 не картинку кэширует, а закэшировал сам HTML, и вот такой код, всё же работает.
Выложил код повторно, чтобы не пудрить людям мозг чтением наших постов. |
| Автор: IDVsbruck 30.5.2008, 22:46 | ||
Ок, только предложу твой код с оптимизацией:
...ну уж больно я люблю компактные решения ... |
| Автор: AKS 31.5.2008, 07:36 |
Такой (for (var i = 0 in img_srcs)) оптимизации я еще не встречал. |
| Автор: Frantishik 31.5.2008, 08:26 |
| IDVsbruck, спасибо огромное за чёткий код.Вы не правы насчёт заинтересованости....я думаю что многие сталкиваюся с такой проблемой. да, это действительно именно то решение которое чаще всего нужно, а именно загрузить все картинки до показа самого сайта и к тому же таким образом легко манипулировать загрузкой документа(показом разных div и т.д.). к сожалению я не смог поучаствовать в дисскусии, но решение проблемы сделал аналогичным 1функция создаёт обьекты 2функция проверяет наличие файла в кеше браузера не один из примеров на всём форуме по предзагрузке картинок не работает! обычно в примерах идёт просто создание обьектов-этого мало! так что этот топик можно смело переносить в документацию. Всем СПАСИБО за помощь и проявленный интерес. Я думаю докопались до истины! |
| Автор: AKS 31.5.2008, 09:50 | ||
??? |
| Автор: IDVsbruck 31.5.2008, 13:16 | ||||
Чисто техническая помарка - я просто переделывал код Гирика и пропустил ляп. Надеюсь, меня из-за этого не четвертуют ... Добавлено через 53 секунды
А тут что не понравилось? |
| Автор: Frantishik 31.5.2008, 14:24 | ||
| AKS, всё довольно просто: 1.выносим скрипт в конец документа 2.Помещаем контент в div и делаем его невидимым в стиле. 3.В конце обхода массива картинок в функции preload делаем видимым
В этом месте можно вызвать любую функцию и будет гарантия, что на момент её выполнения все картинки из массива уже загружены... |
| Автор: IDVsbruck 31.5.2008, 17:05 | ||
document.body.appendChild(document.getElementById("img" + i)); - и что нам не нравится? Хотя я считаю, что добавление к боди не нужно, как настаивает мой оппонент, но с точки зрения синтаксиса строка правильная.
Управление покинет цикл практически мгновенно (в нашем человеческом времяисчислении), а картинки когда загрузятся, тогда и загрузятся. По крайней мере код так и работает - или грузим, или они уже есть в кеше. Что-то я не понимаю интонаций АКС ... Хотя могу предположить, что почти каждый из нас в глубине души считает себя гуру Добавлено через 4 минуты и 44 секунды Да, кстати, повторюсь для тех, кто все-таки читает только последний пост и не читает всей темы: помочь на форуме - это не разжевать задачу, а дать идею. Лично я отношусь именно к таким "советчикам". А если кто-то собирается буквально воспринимать все написанное и, к примеру, вставит код типа for (var i = 0 in array) и будет пытаться его юзать, то он либо дилетант либо дурак. |
| Автор: AKS 31.5.2008, 17:21 | ||||
Откуда возьмется document.getElementById("img" + i), если изображения не были добавлены в структуру документа?
То, что Вы комментируете, было написано для Frantishik'а, который надеялся, что после цикла изображения будут загружены (мне это не надо объяснять). А какие Вы увидели "интонации"? Вижу надпись "код с оптимизацией", смотрю, что это за "оптимизация", пишу, что "оптимизации" на самом деле нет, более того, есть ошибки. Это все - ни больше, ни меньше. Каждому - свое. |
| Автор: Ghirik 31.5.2008, 23:38 | ||||||
В этом Вы малость ошибаетесь. Давайте разберемся, для кого и что является помощю. Обычно, по первому посту можно сразу оценить уровень знаний вопрошающего. Если он запинается в синтаксисе (таких более 50%), то на кой бес ему ваши советы? А если, нужна идея, то обычно люди так и пишут - "Нужна идея, в каком направлении двинуться?" Вот тут то и нужно включать идейный генератор и измеритель оптимальности... Frantishik,
Это Вы о чем написали?
Работают... прекрасно работают, просто ещё не было функции для балбесов - теперь есть. |
| Автор: Frantishik 2.6.2008, 15:57 |
| Если бы я считал себя гуру и был мастером высшего класса, разве я обращался бы за помощью..... И мне интересна не сама идея(я думаю догодаться не сложно,если есть хоть немного логики и знаний в программировании), не код от <html> до </html>, а сама технология работы. Я поблагадарил IDVsbruck, потому что мне его код разьяснил, что помимо создания объекта, его нужно добавить к body. Ghirik, приведите пример с форума, который реально работает. Перед тем как создавать топик, я облазил весь форум, рассмотрел и проработал все примеры(их около 8).... Я занимался системным программированием и мне кажется странным тот факт, что управление покидает цикл практически мгновенно... Тогда что же всё таки загружает картинки и делает эту задержку во время которой и грузятся картинки?.... по поводу балбесов,Ghirik имейте уважение .... если вы считаете мои вопроссы глупыми и отвечаете нехотя, просто пропустите топик..... |
| Автор: IDVsbruck 2.6.2008, 16:22 | ||
Событие onload! ... или проверка на уже загруженную картинку. В цикле мы всего-навсего назначаем событие onload для картинки - и все, и это происходит в считанные миллисекунды. А когда картинка загружается, возникает событие onload, интерпретатор идет в обработчик, назначенный нами в цикле и выполняет нужную функцию и нужный скрипт. Теоретически, если повесить многомегабайтовые картинки, то можно просидеть не один десяток минут (ограниченный сессией), пока не сработают обработчики для ВСЕХ картинок. |
| Автор: Ghirik 2.6.2008, 17:31 | ||||||
Лучше нет способа для понимания технологии, это иметь правильно работающий скрипт оформленный от <html> до </html>. Берите его и изменяйте, вставляйте алерты, смотрите в какие моменты, что происходит. Начинать изучение нужно именно с работающих скриптов. От <html> до </html> имеет очень большое значение для начинающих, т.к., от DOCTYPE зависит работоспособность тех или иных методов JavaScript-а. Можно потратить массу времени, пытаясь разобраться почему не работает скрипт, а потом выяснить, что просто неправильно указан тип документа, и этот метод не работает с таким типом.
Я конечно не буду искать примеры. Зачем? То, что те примеры не заработали у Вас, не означает, что они нерабочие. Есть масса нюансов, которые следует учитывать... Например, Опера не станет загружать изображение на страницу, если оно имеет свойство display:none, для Оперы изображение нужно прогнать через массив. IE и FF - напротив, прекрасно грузят изображение в скрытом виде, но IE игнорирует загрузку в массив и начинает сразу его отдавать на страницу... С контролем события onload изображения, полностью готовой к употреблению функции не было, хотя, обсуждалось неоднократно... А может и была...
Я же не имел Вас ввиду, просто, теперь каждый, кто сделает копи-пасте, задумается... |