Последующая ошибка предварительного просмотра изображения HTML5 CreateObjectURL blob и загрузки обрезки - PullRequest
10 голосов
/ 18 марта 2012

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

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

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

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

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

  • JQuery 1.7.1

  • JQuery Tools 1.2.6

  • JCrop 0.9.9

Шаги - сводка

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

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

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

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

  5. Затем пользователь обрезает изображение с помощью 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 окно .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 для рисования предварительного просмотра.вместо переполнения на основе маржи: скрытое решение.Нужна доработка, тогда я выложу код здесь.

1 Ответ

2 голосов
/ 13 августа 2012

часто ошибочное поведение возникает, когда вы устанавливаете 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

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

...