Страницы

Поиск по вопросам

суббота, 4 января 2020 г.

Обновление фоновых изображений на странице без перезагрузки

#javascript #html #css


Еще раз подчеркну: задача не стоит вывести рандомное изображение. Набор изображений
и их адреса на сервере строго заданы.

Задача: обновлять картинки на сайте, т.к. содержимое файлов с изображениями может
измениться. 
Физически файл с изображением остается лежать по тому же адресу, но т.к. содержимое
файла может измениться, необходимо заставить браузер обновлять отображаемое изображение
принудительно.
Для этого по таймеру добавляю параметр к адресу картинки

setInterval(function(){
       var arr = $(".image-responsive");
       for (var i = 0; i < arr.length; i++ ){
           arr[i].style.backgroundImage = 'url(' + arr[i].style.backgroundImage.slice(4,
-1).replace(/"/g, "").split("?")[0] +  "?" +  Math.random() + ')';
       }
}, 1000);


Изображения обновляются, но перед каждым обновлением происходит задержка и фон остается
какое-то время пустым. Также фон появляется резко. Как это исправить, чтобы убрать
дерганье и паузы?

Обновление 2:
Попытался использовать предзагрузчик - невидимый контейнер, в который подгружаются
изображения, прежде чем установить их в качестве фоновых изображений для нужных блоков
на странице.
С одной картинкой убрать дерганье получилось
http://jsfiddle.net/rGkww/36/
Однако дергается скроллинг. 
С несколькими http://jsfiddle.net/rGkww/41/ меняется только одна картинка, дерганье
картинки по-прежнему, и скроллинг дергается

Обновление 3:
Вроде дерганье убрал, пример кода со множеством изображений
http://jsfiddle.net/rGkww/57/
Осталось дерганье скролла, ну и не совсем уверен в корректности самого решения. Страница
должна быть рассчитана на длительную работу.

Обновление 4:
Убрал дерганье скроллинга
http://jsfiddle.net/rGkww/61/

Обновление 5:

Доработал немного код, чтобы в случае обрыва соединения с сервером не возникало переполнение
памяти, и после восстановления обновление возобновлялось.
http://jsfiddle.net/rGkww/64/
Обновление происходит без проблем.
Однако Iceweasel/Firefox через пару часов падает. Т.к. необходима длительная работа,
это критично. Неясно, проблема в коде или в браузере. Chrome/Chromium спокойно работает
несколько дней. 
    


Ответы

Ответ 1



Вот переделка вашего скрипта без дерганий. Изображения появляются только когда полностью загрузились. Вот что добавилось (прошу обратить внимание на то, что порядок строк очень важен): var i = new Image(); i.onload = function(){alert(i.width);} i.src = 'image.jpg'; // существующее изображение Для демо версии так же прописал счетчик (увеличивающееся число), который показывает рассинхронизацию появления нового числа и изображения. Ну, вы же понимаете да, что для загрузки картинки браузеру нужно время. п.с. я повторю еще раз - вы что-то не то делаете. Загружать ещё раз изображение, которое уже лежит в кеше браузера - не правильно. Никто так не делает. Наоборот пытаются предзагрузить все изображения, чтобы потом показывать их без дерганий ОДНОВРЕМЕННО с текстом. п.п.с. если у вас задача выбрать 1 из миллиона изображений (то есть вы реально не знаете какое изображение к вам придет и именно это вы изображаете в данном вопросе с помощью random()), то тогда нужно в интервале сделать "шаг назад", то есть загружать БУДУЩЕЕ изображение (которое покажется в следующую итерацию). Пример давать сложно, потому что не известно каким образом в реальном проекте у вас контент обновляется. ajax? $(window).load(function() { var num = 0; var randomImages = ['344291068_HdnTo', '344290962_h6JjS', '344291168_nErcq']; setInterval(function() { var rndNum = Math.floor(Math.random() * randomImages.length); var url = 'http://photos.smugmug.com/photos/' + randomImages[rndNum] + '-XL.jpg' + '?random=' + Math.random(); var i = new Image(); i.onload = function() { $(document.body).css({ 'background': 'url(' + url + ')' + ' no-repeat center center fixed', '-webkit-background-size': 'cover', '-moz-background-size': 'cover', '-o-background-size': 'cover', 'background-size': 'cover' }); } i.src = url; num++; $('#home').html(num); }, 3000); }); #home { height: 150px; width: 150px; }


Ответ 2



Таймер одноразовый, что бы между сменой изображений всегда было заданное время таймера (+время на загрузку изображения). var url = 'http://photos.smugmug.com/photos' var images = ['344291068_HdnTo-XL.jpg', '344290962_h6JjS-XL.jpg', '344291168_nErcq-XL.jpg'] new updateBackgroundTimer('real', url, images, 1000) function updateBackgroundTimer(node_id, url, images, timer) { // init node_id = String(node_id) var node = document.getElementById(node_id) if (!node) return false this.node_id = node_id this.node = node url = String(url) if (!images.length) return false for (var i in images) { images[i] = url + '/' + images[i] + '?r=' + Math.random() } shuffleArray(images) // вывод изображний в случайном порядке this.images = images timer = parseInt(timer) if (isNaN(timer) || timer < 1) return false this.timer = timer // model this.start = function() { initTimer() } this.stop = function() { if (this.timer_id) { clearInterval(this.timer_id) this.timer_id = null } } initTimer = function(_this) { return function() { if (_this.timer_id) { clearTimeout(_this.timer_id) _this.timer_id = null } _this.timer_id = setTimeout( function(_this) { return function() { _this.updateImage() } }(_this), _this.timer) } }(this) this.updateImage = function() { var url = this.getImageNext() var image = new Image() image.onload = function(_this, url) { return function() { _this.setImage(url) if (!_this.images_loaded) _this.images_loaded = {} _this.images_loaded[url] = true _this.start() } }(this, url) image.src = url } this.setImage = function(url) { url = String(url) this.node.style.backgroundImage = 'url(' + url + ')' } this.getImageNext = function() { var images = this.images var images_qty = images.length var index = parseInt(this.index) if (isNaN(index) || index < 0 || index >= images_qty) { index = 0 } else { index++ if (index >= images_qty) index = 0 } this.index = index var image = images[index] return image } function shuffleArray(array) { for (var j, x, i = array.length; i; j = parseInt(Math.random() * i), x = array[--i], array[i] = array[j], array[j] = x); } // run this.start() } #real { width: 300px; height: 300px; border: 2px solid red; }


Ответ 3



Обновление 2: .... С одной картинкой убрать дерганье получилось Однако дергается скроллинг. Немного переписали Ваш код, убрали дерганье скролла, таким же образом код меняется и для нескольких картинок: $(window).load(function() { var randomImages = ['344291068_HdnTo', '344290962_h6JjS', '344291168_nErcq']; setInterval(function() { var rndNum = Math.floor(Math.random() * randomImages.length); var src = 'http://photos.smugmug.com/photos/' + randomImages[rndNum] + '-XL.jpg' + '?random=' + Math.random(); $(".preload_hidden").html(""); $(".preload_hidden img").load(function() { var img = src; $("#real").css({ "background": "url(" + img + ")" }); }); }, 1000); }); .preload { width: 300px; height: 300px; #width: 1px; #height: 1px; background-repeat: none; #background-position: -1000px -1000px; #position: absolute; #opacity: 0; border: 2px solid blue; } #real { width: 300px; height: 300px; border: 2px solid red; } .preload_hidden { display: none; } }
Пример на JsFiddle UPDATE написали решение по вопросу автора setInterval(function() { $(".real").each(function(index) { var obj = $(this); d = new Date(); var bg = obj.css("background-image").match(/((http|https):\/\/.*(jpg|png|gif)).*/i)[1] + '?random=' + d.getTime(); console.log(bg); $('').attr('src', bg).load(function() { $(this).remove(); // чтобы избежать утечки памяти obj.css('background-image', 'url(' + bg + ')'); }); }); }, 2000); .real { width: 350px; height: 350px; border: 2px solid red; float: left; } .preload_hidden { display: none; }
Example on Jsfiddle

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

Отправить комментарий