后续的HTML5 CreateObjectURL blob图像预览和裁剪加载问题

10
我试图弄清楚是我的代码有问题还是当前的HTML5文件API实现有问题。
以下代码有效。 重复加载图像后出现错误。
第二次选择文件时,图像 Blob 加载完成后会出现闪烁,然后图像就会消失。 在此之后的选项通常都能正常工作(如果文件很大则可能会出现不稳定的行为)。 重复相同文件选择的过程通常可以解决问题。
非常感谢您的任何帮助。 使用的 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,并且所选文件大小小于 250KB。 如果验证失败,则重置选择。 3. 此时要上传的文件(图像)有效。 接下来,它检查浏览器是否支持 File API CreateObjectURL,方式为 if(typeof window.URL == 'undefined') return; (如果不支持,则跳过下一个步骤) 4. 它将图像 blob 加载到当前图片预览中(用于显示当前图像),并且还将其加载到一个动态生成的图像元素中,该元素添加到具有 jcrop 裁剪功能的 jquery 工具覆盖层中。 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中的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执行时,图像并不总是“准备就绪”的,因此奇怪的行为和使用setTimeout进行额外检查来获取.actualWidth/.actualHeight可能会解决问题。我将进一步调查它。

更新

我有一个工作概念证明,使用FileReader和readAsDataUrl而不是使用CreateObjectURL,并使用CANVAS绘制预览而不是基于边距的overflow:hidden解决方案。需要进行一些改进,然后我将在此处发布代码。


我认为最好使用jCrop API并使用通用处理程序或静态URL来加载您的图像。我制作了一个裁剪器,可以像这样裁剪无限数量的图片(使用从SQL数据库传递图像blob的通用处理程序)-而不使用API会出现一些奇怪的情况... - Piotr Kula
1个回答

2

当你在声明 img.onload 前设置 img.src 时,经常会出现不稳定的行为。

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

希望这能帮到你。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接