Последующий HTML5 CreateObjectURL blob изображение предварительного просмотра и обрезки загрузки ошибка

Я пытаюсь выяснить, поврежден ли мой код или текущая реализация API файлов HTML5.

Код ниже работает. Ошибка повторения процесса после загрузки изображения один раз.

Во второй раз, когда выбран файл, загружается изображение blob, затем появляется мерцание, и изображение исчезает. Последующие выборы после этого обычно работают нормально (иногда бывает неустойчивое поведение, если файл большой). Повторение процесса для одного и того же файла обычно работает (как исправление).

Любая помощь будет принята с благодарностью.

Используемые библиотеки JavaScript

  • JQuery 1.7.1

  • JQuery Tools 1.2.6

  • JCrop 0.9.9

Шаги - сводка

  • Пользователь выбирает файл через традиционный <input type="file" /> диалоговое окно.

  • Обработчик onchange выполняет вход и проверяет, был ли файл если это так, то проверяет, что тип MIME - это изображение /jpeg или image/png и что размер выбранного файла меньше 250 КБ. Если эта проверка не позволяет сбрасывать выбор.

  • В этот момент файл (изображение), который будет загружен, действителен. Затем проверяет, поддерживает ли браузер API-интерфейс API CreateObjectURL через if (typeof window.URL == 'undefined') return; (если это не так, пропускает следующие шаги)

  • Он загружает изображение blob в текущий предварительный просмотр изображения (один используется для отображения текущего изображения), а также для динамически генерируемого элемент изображения, который добавляется в наложение инструментов jquery tools с jcrop обрезка.

  • Затем пользователь обрезает изображение с помощью jcrop и закрывает оверлей, просмотр обрезанного предварительного просмотра изображения, которое будет загружено (только если браузер поддерживает CreateObjectURL, а пользователь обрезал изображение)

Код

HTML

<div style="height: 100px; overflow: hidden; width: 100px; margin-bottom: 5px;">
    <img id="PhotoPreview" alt="Photo" src="/Content/no-photo.png" />
</div>
<input type="file" id="Photo" name="Photo" onchange="photoChanged(this.files)" />
<input type="hidden" id="PhotoCrop" name="PhotoCrop" value="" />

JavaScript   window.URL = window.URL || window.webkitURL;

function photoChanged(files) {
    if (!files.length) return;
    var file = files[0];
    if (file.type != 'image/jpeg' && file.type != 'image/png') {
        alert('The photo must be in PNG or JPEG format');
        $("#Photo").val('');
        return;
    }
    var fileSizeLimit = 250;
    var fileSize = file.size / 1024;
    if (fileSize > fileSizeLimit) {
        var fileSizeString = fileSize > 1024 ? (fileSize / 1024).toFixed(2) + "MB" : (fileSize).toFixed(2) + "KB";
        alert("The photo file size is too large, maximum size is " + fileSizeLimit
                + "KB. This photos' file size is: " + fileSizeString);
        $("#Photo").val('');
        return;
    }

    if (typeof window.URL == 'undefined') return;

    var preview = document.getElementById('PhotoPreview');
    $(preview).removeClass('profile-photo');
    preview.src = window.URL.createObjectURL(file);
    preview.onload = function () {
        var img = new Image();
        $("#PhotoOverlay div").empty().append(img);
        window.URL.revokeObjectURL(this.src);
        img.src = window.URL.createObjectURL(file);
        img.onload = function () {
            window.URL.revokeObjectURL(this.src);
            $(this).Jcrop({
                onSelect: onImageCropSelect,
                aspectRatio:
                310 / 240,
                minSize: [100, 100],
                setSelect: [0, 0, 100, 100]
        });

        $("#PhotoOverlay")
            .css({ width: this.width + 'px', : 'auto'})
            .overlay()
            .load();
        };
    };
}

function onImageCropSelect(e) {
    $("#PhotoCrop").val(e.x + ',' + e.y + ',' + .x2 + ',' + e.y2);

    var rx = 100 / e.w;
    var ry = 100 / e.h;

    var height = $("#PhotoOverlay div img").height();
    var width = $("#PhotoOverlay div img").width();

    jQuery('#PhotoPreview').css({
        width: Math.round(rx * width) + 'px',
        height: Math.round(ry * height) + 'px',
        marginLeft: '-' + Math.round(rx * e.x) + 'px',
        marginTop: '-' + Math.round(ry * e.y) + 'px'
    });
}

$(function () {
    $("#PhotoOverlay").overlay({
        mask: {
            color: '#ebecff',
            loadSpeed: 200,
            opacity: 0.9
        }
    });
});

Не стесняйтесь использовать код (мой вклад за любую полученную помощь).

Обновление

Я столкнулся с другим вопросом о stackoverflow относительно подобной проблемы (загрузка изображения, затем исчезающая) в отношении использования JCrop. Я сейчас ставлю на JCrop, являющегося виновником.

Я также прочитал, что при выполнении img.onload изображение не всегда "готово", поэтому странное поведение и дополнительные проверки на .actualWidth/.actualHeight с помощью setTimeout могут решить проблему. Я исследую это.

Обновление

У меня есть рабочее доказательство концепции с использованием FileReader и readAsDataUrl вместо использования CreateObjectURL и использование CANVAS для создания предварительного просмотра вместо переполнения на основе margin: hidden. Нужно немного уточнить, тогда я отправлю код здесь.

Ответ 1

часто ошибочное поведение возникает, когда вы устанавливаете img.src перед объявлением img.onload

function imageLoadHandler() { ... }

var img = new Image();
img.onload = function() { imageLoadHandler() }
img.src = window.URL.createObjectURL(file);
if(img.complete) { imageLoadHandler() } //fix for browsers that don't trigger .load() event with image in cache

надеюсь, что это поможет