2017-02-14 3 views
2

Это может выглядеть как дублированный вопрос, но я уверяю вас, что это не так.Javascript Image.onload запускает слишком рано

Я загружаю несколько динамических изображений из вызова AJAX, предоставляемого сервлетом на стороне сервера. Мне нужно расколоть изображение на три части, но я не могу этого сделать, пока изображение не будет загружено. Это подводит меня к моей проблеме. У меня есть триггер onload для каждого изображения, но он срабатывает до того, как доступны атрибуты изображения (например, высота, ширина и т. Д.). Таким образом, мой код не справляется с обработкой ошибок.

var imageData = []; 

$(document).ready(function() { 
    preLoadImages(); 
}); 

function preLoadImages() { 
    <c:forEach var="table" items="${tables}"> 
    var tmpImage = new imageObject(<c:out value="${table.tableRowId}" />); 
    imageData.push(tmpImage); 
    </c:forEach> 

    for (var i = 0; i < imageData.length; i++) { 
     ajaxGetmainImages(i); 
    } 
} 

function imageObject(id) { 
    this.id = id; 
    this.mainImage = new Image(); 
    this.topImage = new Image(); 
    this.middleImage = new Image(); 
    this.bottomImage = new Image(); 
} 

function split_3(i) { 
    var canvas = document.createElement('canvas'); 
    var ctx = canvas.getContext("2d"); 

    if (imageData[i].mainImage.height > 2500) { 
     $("#error_container-" + imageData[i].id).attr('display', "none"); 
     //document.getElementById('error_container').style.display = "none"; 

     var newWidth = imageData[i].mainImage.width; 
     var newHeight = imageData[i].mainImage.height/3; 
     canvas.width = newWidth; 
     canvas.height = newHeight; 

     ctx.drawImage(imageData[i].mainImage, 0, 0, newWidth, newHeight, 0, 0, newWidth, newHeight); 
     imageData[i].topImage.src = canvas.toDataURL(); 

     ctx.drawImage(imageData[i].mainImage, 0, (newHeight), newWidth, newHeight, 0, 0, newWidth, newHeight); 
     imageData[i].middleImage.src = canvas.toDataURL(); 

     ctx.drawImage(imageData[i].mainImage, 0, ((newHeight * 2)), newWidth, newHeight, 0, 0, newWidth, newHeight); 
     imageData[i].bottomImage.src = canvas.toDataURL(); 

     $("#left_image-" + imageData[i].id).attr('src', imageData[i].topImage.src); 
     $("#right_image-" + imageData[i].id).attr('src', imageData[i].bottomImage.src); 
    } 
    else { 
     $("#slider_container-" + imageData[i].id).attr('display', "none"); 
     $("#error_image-" + imageData[i].id).attr('src', imageData[i].mainImage.src); 
    } 

} 

function ajaxGetmainImages(i) 
{ 
    $.ajax({ 
     type: "GET", 
     url: baseURL + '/admin/' + imageData[i].id, 
     dataType: "json", 
     async: true, 
     success:function(data){ 
      imageData[i].mainImage.onload = split_3(i); 
      imageData[i].mainImage.src = "data:image/jpg;base64," + data.image; 
      //imageData[i].mainImage.addEventListener("load", split_3(i)); 
     }, 
     error:function(result){ 
      //$("#" + id + 'status').html("<img src='../resources/img/status-unknown-16.png' alt='Unknown'>"); 
     } 
    }); 
} 

Идентификатор изображения предоставляется с помощью модели сервлета, который предоставляет страницу. При этом я создаю уникальные URL-адреса для опроса для каждого изображения. Этот код работает. Я работаю на отдельной странице, где я имею дело только с одним изображением (изображение разделяется так, что слайдер может использоваться для сравнения изображений). Однако, когда я пытаюсь использовать несколько изображений, высота изображения всегда равна 0 во время функции onload. Если я установил точки останова в функции split_3, я вижу, что когда обрабатывается изображение next, у предыдущего теперь есть ненулевое значение высоты (правильное значение).

Я пробовал Chrome Stable, Chrome Beta, Chrome Dev, Firefox и Opera, и результаты все одинаковы. onload, похоже, слишком рано запускает, и я понятия не имею, почему.

Редактировать: некоторые дополнительные сведения. Изображения в конечном итоге загружаются. Если код на стороне сервера не может получить правильное изображение, он служит для заполнения по умолчанию (следовательно, else> «error_image»). Но местозаполнитель не нужно разделить. Итак, что я получаю на своей странице, это изображение высотой 3 раза в месте заполнения ошибки. Это конечная проблема.

+0

'imageObject' похоже, не имеет свойства' tableImage'. Вы делаете 'imageData [i] .tableImage.onload = split_3 (i);'. Даже если 'imageObject' имеет свойство' tableImage', где вы устанавливаете src? –

+0

@VivekAthalye спасибо за то, что нашли время. Я перепутал при копировании кода. Ваши наблюдения верны, но мой код не имеет этой проблемы. Я исправил свой пост. – Chris

ответ

1

Спасибо всем, кто откликнулся. Я обнаружил проблему. Проблема заключалась в том, что я звоню метод OnLoad как таковой:

tableData[i].tableImage.onload = split_3(i); 

Который называет его сразу, потому что это не ссылка. Я исправил код следующим образом.

tableData[i].tableImage.indexId = i; 
tableData[i].tableImage.onload = split_3; 
tableData[i].tableImage.src = "data:image/jpg;base64," + data.image; 

Я также сохранил текущий индекс внутри самого объекта изображения. Таким образом, я могу перезвонить, когда запускается onload.

function split_3() { 
    var i = this.indexId; 

И остальная часть кода работает без каких-либо изменений.

2

Аргумент addEventListener должен быть ссылкой на функцию. Вы вызываете функцию немедленно и передаете результат в addEventListener. Оно должно быть:

imageData[i].mainImage.addEventListener("load", function() { 
    split_3(i)); 
}); 

или onload:

imageData[i].onload = function() { split_3(i); }; 
+0

Спасибо, я исправил вложенный код. То, что я первоначально вставил, было всего лишь тем, что я тестировал (безуспешно). – Chris

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