JCrop (jQuery) иногда не загружает область изображения/обрезки

У меня довольно простая проблема, но я стал не понимаем, что вызывает проблему. В одном из моих приложений я использую jCrop как небольшую надстройку для обрезки изображений для размещения в баннерах/заголовках и т.д. Эти шаги будут предприняты:

1) Select an image (using CKFinder for this, CKFinder returns the image path to an input field)
2) Click a button to load the image
3) Crop the image
4) Save the image

примерно в 75% случаев все идет по плану, однако в других 25% случаев jCrop не загружает область обрезки и оставляет ее пустой. Вот код jQuery, который я использую:

jQuery('#selectimg').live('click', function(e) { 
  e.preventDefault();
  var newsrc = jQuery('#img2').val();
  jQuery('#cropbox').attr('src', newsrc);
  var jcrop_api = jQuery.Jcrop('#cropbox', {
    boxWidth: 700, 
    boxHeight: 700,
    onSelect: updateCoords,
    onChange: updateCoords
  });
  //Some other JS code come here for buttons (they work all the time)
});

Я заметил, что когда я оставил часть, где #cropbox трансформируется в области подкачки, то изображение загружается просто отлично, поэтому ошибка заключается в части var = jcrop_api, но я медленно начинаю думать, что там не является решением для этого...

Это то, что я пробовал до сих пор:

Создание div <div id="cropper-box"></div> и использование jQuery('#cropper-box').append('<img src="" id="cropbox" />');, а затем установите значение. Я попробовал то же самое, но установил изображение src за 1 шаг, а не потом.

Я попытался поместить заполнитель на страницу <img src="placeholder.png" id="cropbox" /> и изменить источник при нажатии кнопки. Это работает, но cropperarea остается размером с изображение (300x180px или что-то еще) и не становится больше, как должно быть.

//Правка:

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

В месте, где должен располагаться обрезчик, есть пятно размером около 10x10 пикселей, в котором появляется значок обрезки (знак плюса).. но, как было сказано ранее: изображение не отображается.

//Правка 2:

Итак, я взял источники для первой и второй попыток для одного и того же изображения. Как было сказано перед первой попыткой, изображение не будет загружаться должным образом, а вторая попытка - (только когда вторая попытка - это одно и то же изображение (!!)).

Выбранный источник страницы показывает 1 разницу, которая есть, сначала попробуйте:

<img style="position: absolute; width: 0px; height: 0px;" src="http://95.142.175.17/uploads/files/Desert.jpg">

вторая попытка:

<img style="position: absolute; width: 700px; height: 525px;" src="http://95.142.175.17/uploads/files/Desert.jpg">

Я думаю, что это образ, заменяемый jCrop, но это полная загадка, почему он ставит 0 heigth/width там, где первый и правильный размеры второй раз.

Ответы

Ответ 1

Хорошо, ребята, если кто-то еще столкнется с этой проблемой:

jCrop kinda перепутался, если действия загрузки изображения и применения jCrop к нему поставлены в очередь слишком быстро после eachother. Мне все еще кажется странным, что вторая попытка работает идеально, но я думаю, что это имеет какое-то отношение к размерам кешированных изображений, которые распознаются DOM страницы или что-то в этом роде.

Решение, с которым я столкнулся, состояло в создании функции, которая преобразует #cropbox в область jCrop, а затем устанавливает интервал в 2 секунды, чтобы дать jCrop некоторое время, чтобы распознать изображение и его размеры, а затем преобразовать элемент.

Это часть используемого html (с предварительным загрузчиком):

<div id="cropper-loading" style="display: none;"><img src="images/analytics/ajax-loader.gif" /></div>
<img id="cropbox" src="images/placeholder.png" style="display: none;" />

Как вы можете видеть, как изображение обрезки, так и обрезка обрезки контейнера скрыты, поскольку они не нужны мгновенно. Вы могли бы отобразить местозаполнитель, если хотите. Тогда эта форма HTML используется:

<input name="image2" id="img2" type="text" readonly="readonly" onclick="openKCFinder(this)" value="click here to select an image" style="width: 285px;" />  <button class="button button-blue" type="submit" name="load" id="selectimg">Load Image in cropper</button>

В моем случае я использовал KCFinder для загрузки изображений (это часть CKEditor, действительно стоит посмотреть!), KCFinder обрабатывает закачки, переименование и т.д., и после выбора возвращает выбранный путь изображения (относительный/абсолютный настраивается ) в поле ввода.

Затем при нажатии #selectimg этот код вызывается:

jQuery('#selectimg').click(function(e) { 
    e.preventDefault();
    jQuery('#cropper-loading').css('display', 'block');

    var newsrc = jQuery('#img2').val();

    jQuery('#cropbox').attr('src', newsrc);
    jQuery('#img').val(newsrc);

    function createJcropArea() {
        jQuery('#cropper-loading').css('display', 'none');                                      
        jQuery('#cropbox').css('display', 'block');
        var jcrop_api = jQuery.Jcrop('#cropbox', {
            boxWidth: 700, 
            boxHeight: 700,
            onSelect: updateCoords,
            onChange: updateCoords
        });
        clearInterval(interval);
    }
    var interval = setInterval(createJcropArea, 2000);
});

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

Затем местоположение изображения загружается из поля ввода и копируется в другое (#img), это поле используется для обработки изображения впоследствии (PHP использует значение #img для загрузки этого изображения). Также одновременно #cropbox src устанавливается на новое изображение.

И вот часть, которая решила мою проблему:

Вместо прямой активации jCrop я создал функцию, которая:

1) hides the loading icon
2) displays the image
3) converts #cropbox into a jCrop area
4) clean the interval (otherwise it would loop un-ending)

И после этой функции вы можете видеть, что, чтобы быть сохраненным, я задерживал 2 секунды до того, как область jCrop будет преобразована.

Надеюсь, что это поможет любому в будущем!

Приветствия и благодарности за мышление @vector и того, кто еще это сделал, -)

Ответ 2

Создание объекта "Изображение" и настройка атрибута "src" не применяются, чтобы вы могли обрабатывать изображение, как оно уже было загружено. Кроме того, предоставление любого фиксированного интервала таймаута не гарантирует, что изображение уже загружено.

Вместо этого вы должны настроить обратный вызов "onload" для объекта Image, который затем инициализирует объект Jcrop:

var src = 'https://example.com/imgs/someimgtocrop.jpg'; 
var tmpImg = new Image();
tmpImg.onload = function() {
   //This is where you can safely create an image and a Jcrop Object
};
tmpImg.src = src; //Note that the 'src' attribute is only added to the Image Object after the 'onload' listener was defined

Ответ 3

Попробуйте библиотеку ребер на репо здесь: https://github.com/tapmodo/Jcrop

Это должно решить вашу проблему. Строки, которые были изменены для решения вашей проблемы:

// Fix size of crop image.
// Necessary when crop image is within a hidden element when page is loaded.
if ($origimg[0].width != 0 && $origimg[0].height != 0) {
  // Obtain dimensions from contained img element.
  $origimg.width($origimg[0].width);
  $origimg.height($origimg[0].height);
} else {
  // Obtain dimensions from temporary image in case the original is not loaded yet (e.g. IE 7.0).
  var tempImage = new Image();
  tempImage.src = $origimg[0].src;
  $origimg.width(tempImage.width);
  $origimg.height(tempImage.height);
}

Ответ 4

Не вызывайте эту функцию onChange : updateCoords

Попробуйте без него, и он будет работать на мобильных телефонах.

Вы можете создать base64 напрямую и показать их как изображение, где хотите.

Ответ 5

Здесь мое странное, но фантастическое решение:

if (obj.tagName == 'IMG') {
  var tempImage = new Image();
    tempImage.src = $origimg[0].src;
    $origimg.width(tempImage.width);
    $origimg.height(tempImage.height);
  if ($origimg[0].width > 1 && $origimg[0].height > 1) {
    $origimg.width($origimg[0].width);
    $origimg.height($origimg[0].height);
  } else {
    var tempImage = new Image();
    tempImage.src = $origimg[0].src;
    $origimg.width(tempImage.width);
    $origimg.height(tempImage.height);
     //console.log('error'+$origimg[0].width + $origimg[0].height);
  } 

Ответ 6

Не может быть самым изящным решением, но, возможно, полезно быстро исправить:

Вычисление ширины и высоты изображения на стороне сервера и установка его вместе с URL-адресом элемента изображения исправили проблему для меня.

Ответ 7

Я знаю, что это старо, но это происходило случайно для моей установки в последнее время. Обнаружил, что это связано с тем, что изображения не загружаются до того, как jCrop будет проинсталлирован.

Все, что нужно для исправления, заключалось в том, чтобы обернуть материал инициализации jCrop внутри

$(window).on("load", function () { //jcrop stuff here });

И с тех пор он хорошо работает.