2013-09-07 5 views
1

Я пытаюсь сравнить соотношение сторон контейнера с отношением сторон к ряду изображений и добавить к изображениям портрет или пейзаж. Кроме того, я пытаюсь обнаружить очень высокие/широкие изображения (например, большие панорамы) на основе определенного допуска. У меня есть основная функциональность, работающая here (первые два изображения имеют кнопку «увеличить» в верхнем левом углу).Сохранять значения из каждого цикла и использовать в другой функции

Теперь я пытаюсь разделить функцию, поэтому, когда я изменяю размер страницы, сценарий не вычисляет отношения всех изображений снова (var i_ratio), он просто сравнивает их с новым коэффициентом контейнера (var c_ratio). Мой пример разработки - here.

Я думаю, что моя проблема, я не знаю, как:

  • Убедитесь, что вторая функция запускается после первого завершения
  • Передайте значения из i_ratio от первой функции к следующим

В примере dev есть консольный журнал, который показывает, что i_ratio не определена во 2-й функции, но при изменении размера окна он получает значение - не уверен, что происходит.

// Get window aspect ratio 
var container = $('.main'); 
var c_ratio = container.width()/container.height(); 
var i_ratio; 

function imageRatios() { 
    // Get original dimensions of image (IE8+) 
    if (this.naturalWidth) { 
    i_width = this.naturalWidth; 
    i_height = this.naturalHeight; 
    } else { 
    // Get original dimensions of image with JQuery 
    i_width = this.width; 
    i_height = this.height; 
    } 
    i_ratio = i_width/i_height; 
    // Don't allow images to get bigger than their original size 
    $(this).css('max-width', i_width).css('max-height', i_height); 
} 

function setClass() { 
    console.log('number of images: '+images.length+', i_ratio from imageRatios function: '+i_ratio); 
    // Add ratio classes  
    if (c_ratio > i_ratio) { 
    $(this).parent('li').removeClass('landscape').addClass('portrait'); 
    } else { 
    $(this).parent('li').removeClass('portrait').addClass('landscape'); 
    } 
    // Identify long/tall panoramas and add zoom button 
    tolerance = c_ratio/i_ratio; 
    if (tolerance < 0.3 || tolerance > 5) { 
    $(this).after('<div class="zoom">&#xf065;</div>'); 
    } else { 
    $(this).remove('.zoom'); 
    } 
    // Show/hide zoomed image 
    var img = $(this); 
    $(this).next('.zoom').click(function() { 
    if (img.siblings('.big_image').size() > 0) { 
     $('.big_image').remove(); 
    } else { 
     $(this).after('<div class="big_image"><img src="'+$img.attr('src')+'"></div>');   
    } 
    }); 
} 

// Get images 
var images = $('.main img'); 
images.each(function(i) { 
    if (this.complete) { 
    imageRatios.call(this); 
    setClass(); 
    } else { 
    this.onload = imageRatios; 
    setClass(); 
    } 
}); 

// Update ratio class on resize 
$(window).on("throttledresize", function() { 
    var c_ratio = container.width()/container.height(); 
    images.each(function() { 
    setClass(); 
    }); 
}); 
+0

включают JavaScript для функций в вашем вопросе, пожалуйста – DGS

+0

соответствующий код включен, спасибо. – daviestar

+0

Ну, вы знаете, что вы можете передать аргументы функциям правильно? Кажется, вы используете глобальные переменные для обмена данными между функциями, что делает ваш код менее гибким и понятным. – plalx

ответ

1

Пару вопрос - это будет непроверенной, так что вы, возможно, потребуется настроить немного, чтобы получить это право

  • При инициализации изображений вы вызываете setClass сразу после установки обработчика выгрузки. Обработчик является асинхронным, поэтому вызов setClass немедленно приведет к неопределенному значению, которое вы видите в консоли.
  • Все изображения сохраняются в одной и той же переменной.Вам нужно будет настроить, что для их хранения на изображение
  • при вызове setClass, контекст не создается при вызове setClass так this будет глобальный объект

Получить изображения логика может быть настроен на что-то вроде этого:

// Get images 
var images = $('.main img'); 
images.each(function(i) { 
    if (this.complete) { 
    imageRatios.call(this, i); 
    setClass.call(this, i); // <== call with image as the context and pass its index 
    } else { 
    // Wrap the calls to imageRatios & setClass in the callback so 
    // they can be called sequentially 
    this.onload = function() { 
     imageRatios.call(this, i); 
     setClass.call(this, i); // <== call with image as the context and pass its index 
    }; 
    } 
}); 

Throttled изменение размера может быть изменен, чтобы что-то вроде:

// Update ratio class on resize 
$(window).on("throttledresize", function() { 
    c_ratio = container.width()/container.height(); // <== remove var - needs to be available to other functions in this closure (already declared at top) 
    // TODO: Just need to update class, not recalculate image ratios on resize 
    images.each(function(i) { 
    setClass.call(this,i); // <== call with image as the context and pass its index 
    }); 
}); 

imageRatios в:

var i_ratio = [];   // <== use an array of values indexes will match image indexes 

    function imageRatios(i) { // <== change to accept an index 
    var i_width, i_height; // <== declare as local variables 

    // Get original dimensions of image (IE8+) 
    if (this.naturalWidth) { 
     i_width = this.naturalWidth; 
     i_height = this.naturalHeight; 
    } else { 
    // Get original dimensions of image with JQuery 
     i_width = this.width; 
     i_height = this.height; 
    } 
    i_ratio[i] = i_width/i_height; // <== set the ratio using the passed in index 
    // Don't allow images to get bigger than their original size 
    $(this).css('max-width', i_width).css('max-height', i_height); 
    } 

setClass к:

function setClass(i) { // <== Change to accept an index 
    var tolerance; // <== Declare as local variable 
    console.log('number of images: '+images.length+', i_ratio from imageRatios function: '+i_ratio); 
    // Add ratio classes  
    if (c_ratio > i_ratio[i]) { // <== Use the index to get the right ratio 
     $(this).parent('li').removeClass('landscape').addClass('portrait'); 
    } else { 
     $(this).parent('li').removeClass('portrait').addClass('landscape'); 
    } 
    // Identify long/tall panoramas and add zoom button 
    tolerance = c_ratio/i_ratio[i]; // <== Use the index to get the right ration 
    if (tolerance < 0.3 || tolerance > 5) { 
     $(this).after('<div class="zoom">&#xf065;</div>'); 
    } else { 
     $(this).remove('.zoom'); 
    } 
    // Show/hide zoomed image 
    var img = $(this); 
    $(this).next('.zoom').click(function() { 
     if (img.siblings('.big_image').size() > 0) { 
     $('.big_image').remove(); 
     } else { 
     $(this).after('<div class="big_image"><img src="'+$img.attr('src')+'"></div>');   
     } 
    }); 
    } 
+0

thankyou! Я так много узнал из этого кода. было несколько синтаксических ошибок, которые я смог исправить. вы хотите, чтобы я обновил ваш ответ с помощью исправленного кода? не уверен в SO etiquette :) если нет, вы можете найти рабочий код здесь http://www.houseofyum.co.uk/static/gallery/index5.html – daviestar

+0

Я только что сделал пару обновлений, может быть, я их поймал? Если нет, разместите их здесь, и я могу обновить их. Проверьте мою историю изменений, чтобы убедиться, что мы поймали те же проблемы. – dc5

+0

@ daviestar - на вашем сайте ваша логика big_image терпит неудачу в этой строке: '$ (this) .after ('

');': '$ img не определен' – dc5

0

Ваша проблема с неопределенным значением происходит от этого кода

images.each(function (i) { 
    if (this.complete) { 
     imageRatios.call(this); 
     setClass(); 
    } else { 
     this.onload = imageRatios; 
     setClass(); 
    } 
}); 

Это устанавливает OnLoad дозвона каждого изображения быть imageRatios, а затем вызывает setClass() Это, однако, не ждать, пока onload событие не было уволен, чтобы продолжить до setClass попробуйте что-то вроде этого

images.each(function (i) { 
    if (this.complete) { 
     imageRatios.call(this); 
     setClass(); 
    } else { 
     this.onload = function() { 
      imageRatios(); 
      setClass(); 
     }; 
    } 
}); 

whi ч будет вызывать imageRatios() и затем setClass() в таком порядке, когда onload событие вызывается для изображения

+0

спасибо, это имеет смысл. однако вместо «undefined» консоль теперь говорит «Не номер». Я обновил свой пример своим кодом здесь: http://www.houseofyum.co.uk/static/gallery/index4.html – daviestar

Смежные вопросы