Как предварительно загрузить фоновые изображения без жесткого кода с помощью jQuery?

Это старый вопрос о том, как предварительно загружать фоновые изображения css, но с небольшим поворотом: фоновые изображения устанавливаются через jQuery, поскольку они из Vimeo. Каждое фоновое изображение представляет собой видеоизображение из vimeo, поэтому я устанавливаю фон, используя URL миниатюры vimeo при загрузке сайта. Можно ли как-то предварительно загрузить эти изображения? У меня есть оверлей, который я хочу исчезнуть при загрузке контента, но, несмотря на мои усилия, фоновые изображения все еще заметно загружаются, когда оверлей исчезает!

Вот некоторый (не очень красноречивый) код, который я пробовал:

var count = $('.video_stub').length;    
$('.video_stub').each(function(index) {
    var bgUrl = $(this).data('thumb');
    $('<img/>')[0].src = bgUrl;
    if(index == (count - 1)) {
        $('.video_stub').each(function(i) {
        var bgUrl = $(this).data('thumb');
        // Set the video thumb's background using the vimeo thumb image
        $(this).css('background-image', 'url(' + bgUrl + ')');
            if(index == (count - 1)) {
                $('#temp_overlay').fadeOut('slow');
            }
        });
    }
});

Есть идеи? Большое спасибо заранее.

ИЗМЕНИТЬ:

Я пробовал этот код, но безуспешно. Мне интересно, это проблема масштаба? Возможно, я не могу получить доступ к переменной index из обратного вызова загрузки:

// Set video thumb click handler
var count = $('.video_stub').length;

// Set video thumb click handler
// Iterate through each video stub
$('.video_stub').each(function(index) {
    var bgUrl = $(this).data('thumb');
    $('<img/>').attr('src', bgUrl).load(function() {
        $('.video_stub:eq(' + index + ')').css('background-image', 'url(' + bgUrl + ')');
    });
    if(index == (count - 1)) {
        $('#temp_overlay').fadeOut('slow');
    }
});

Я старался:

$('<img/>').attr('src', bgUrl).load(function() {
    $(this).css('background-image', 'url(' + bgUrl + ')');
});

но безрезультатно.


person Hendeca    schedule 25.09.2012    source источник
comment
Спасибо за редактирование j08691, не хотел оставлять так много произвольных пробелов: P   -  person Hendeca    schedule 26.09.2012


Ответы (4)


Следующее должно работать:

var video_stubs = $('.video_stub');
var loaded = [];
video_stubs
  .each(function(){
    /// store stub as a var so we can correctly access it in the callback
    var stub = $(this);
    /// get the URL as usual
    var bgURL = stub.data('thumb');
    /// create a temporary image that tells the browser to load a specific
    /// image in the background
    $('<img />')
      /// define our load event before we set the src value otherwise the
      /// load could happen from cache before we've even defined a listener
      .load(function(){
        /// set the background image $(this) no longer points to stub,
        /// it actually points to the temporary image.. so instead
        /// use the stub var we've created outside of this scope
        stub.css('background-image', 'url(' + bgURL + ')');
        /// store a list of what we've loaded - mainly for the loaded.length 
        /// count - but storing this information could be useful elsewhere
        loaded.push( bgURL );
        /// test that we've all loaded (remember this can occur in any order)
        /// so keeping an incrementing count is better than assuming the last
        /// image we try and load will be the last image to load completely.
        if ( loaded.length == video_stubs.length ) {
          /// finalise only after all is loaded
          $('#temp_overlay').fadeOut('slow');
        }
      })
      /// set the src value, once loaded the callback above will run
      .attr('src', bgURL)
    ;
  })
;

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

person Pebbl    schedule 25.09.2012
comment
Мне нравится это решение, и оно имеет смысл, но почему-то фоновые изображения не загружаются после исчезновения оверлея... Я понятия не имею, почему! Этот код кажется, что он должен работать отлично. - person Hendeca; 26.09.2012
comment
@GionaF спасибо :) Хендека, вы пытались добавить alert/console.log, чтобы убедиться, что bgURL устанавливается с правильным фоновым путем... и что фоновые пути действительно видны как изображения (т.е. вставьте путь в браузере и убедитесь, что он загружается) - кроме этого я не знаю, что предложить (не видя живого примера вашего сайта). - person Pebbl; 26.09.2012
comment
@Hendeca Кроме того, как вы определяете данные «большого пальца» на заглушке ..? - person Pebbl; 26.09.2012
comment
@pebbl О боже, мне придется считать это еще одним из моих эпических умственных способностей. Я по глупости поместил URL-адрес большого пальца vimeo в качестве атрибута данных вместо того, чтобы просто написать встроенный стиль при создании элементов видеозаглушки. Теперь я могу использовать традиционный предварительный загрузчик :P извините, ребята, я идиот! - person Hendeca; 26.09.2012
comment
Если бы кто-то более опытный мог бы помочь мне с протоколом для такой ситуации? По сути, мой вопрос сейчас довольно спорный, несмотря на все ваши полезные ответы. Извини за это. Должен ли я удалить этот вопрос? - person Hendeca; 26.09.2012
comment
Дох! ну что ж, C'est la vie :) Ум, это все еще вопрос с ответами imo, каждый из которых имеет смысл сам по себе (вполне может быть, что у вас не было возможности получить значения большого пальца перед рендерингом HTML, так что вопрос останется в силе). Так что я бы оставил это для будущих людей, если бы это был я;) В конце концов, это то, о чем stackoverflow... для людей, которые еще не знают, что им нужна помощь SO. - person Pebbl; 26.09.2012
comment
Оставьте это для других людей, которые сочтут ответ @pebbl полезным;) и откройте новый вопрос для вашей обновленной ситуации. - person Giona; 26.09.2012
comment
Должен ли я просто оставить вопрос без принятого ответа или создать его и принять? - person Hendeca; 27.09.2012
comment
@Hendeca StackOverflow поощряет добавление вопроса с вашим собственным ответом - я думаю, что они действительно надеются на более обобщенные вопросы - но это все равно может оказаться полезным для кого-то еще, так что да, вы можете добавить ответ о том, что вы полностью изменили свой подход. В то же время вы могли бы объяснить, что вы подразумеваете под «традиционным предварительным загрузчиком», так как это также может помочь другим. - person Pebbl; 27.09.2012

Если вам действительно нужно, чтобы изображения были видны на 100% после исчезновения оверлея, попробуйте удалить его при загрузке $(window).

if(index == (count - 1)) {
    $(window).on('load',function(){
        $('#temp_overlay').fadeOut('slow');
    }
}    

Но будьте осторожны, потому что пользователям придется ждать загрузки каждого контента (внутреннего и внешнего), прежде чем оверлей исчезнет. Может быть, вы можете добавить ссылку «пропустить загрузку».

person Giona    schedule 25.09.2012
comment
Я использую $(document).ready, но не вижу, как это поможет, поскольку фоновые изображения загружаются через Javascript. Кажется, это все равно будет иметь тот же эффект, поскольку функция $(window).load срабатывает до загрузки изображений. - person Hendeca; 26.09.2012
comment
Добавьте слушателя после того, как вы включите изображения... проверьте мое редактирование - person Giona; 26.09.2012
comment
О, я вижу! Вау, ты не шутил насчет времени загрузки. Около полной минуты. Кажется непрактично длинным. Я чувствую, что если бы я мог просто ориентироваться на фоновые изображения css, это сделало бы более разумный предварительный загрузчик. - person Hendeca; 26.09.2012
comment
Да, думаю, да (может быть, но, может быть, целая минута просто вызвана загрузкой большого пальца Vimeo). Но не могу придумать, как добавить слушателя ко всем из них... Дай подумать еще, хе-хе - person Giona; 26.09.2012
comment
Начинаем рассматривать кеширование изображений на стороне сервера, так как видео не будут меняться после загрузки. Может, это более разумное решение? Действительно ли это значительно уменьшит время загрузки при загрузке с сервера вместо сервера Vimeo? - person Hendeca; 26.09.2012
comment
Конечно, иногда API Vimeo также может быть недоступен (или очень медленным), поэтому он будет загружаться, загружаться и загружаться до истечения времени ожидания запроса. Если вы можете получить их раз в неделю с помощью php, это, безусловно, лучший сценарий. Если, конечно, кто-то не предложит более разумное решение. - person Giona; 26.09.2012

Вы можете проверить, было ли загружено изображение с помощью этой функции jQuery:

$('img').load(function() {
        $('#temp_overlay').fadeOut('slow');
});
person jacek_podwysocki    schedule 25.09.2012
comment
OP говорит о фоновых изображениях, так что это не сработает ... В любом случае, ваша отправная точка лучше, чем моя, но будет сложно добавить слушателя для каждого изображения, которое он добавляет динамически :-) - person Giona; 26.09.2012
comment
Верно... Другим обходным решением является использование следующей функции, которая гарантирует, что после предварительной загрузки изображений будут предприняты определенные действия: ditio.net/2010/02/14/jquery-preload-images-tutorial-and-example Это работает для изображений, которые можно динамически извлекать как как только вы сначала определите каждую переменную изображения - person jacek_podwysocki; 26.09.2012

Я использовал queryLoader2 в качестве предварительного загрузчика, который анализирует изображения и фоновые изображения на сайте. Однако я добавлял некоторые фоновые изображения через javascript (вместо того, чтобы записывать их в css или в тег стиля каждого элемента), поэтому предварительный загрузчик не мог фактически загрузить эти изображения.

После того, как я изменил код, включив атрибут фонового изображения в тег «стиль» каждого элемента, я смог успешно загрузить изображения!

person Hendeca    schedule 27.09.2012