随后的HTML5 CreateObjectURL blob图像预览和裁剪加载错误

时间:2012-03-18 12:07:21

标签: jquery html5 jquery-tools jcrop

我正在试图弄清楚我的代码是否有问题或当前的HTML5 File API实现。

下面的代码。在加载图像一次后重复该过程时会出现错误。

第二次选择文件时,图像斑点会加载,然后出现闪烁,图像消失。之后的后续选择通常可以正常工作(如果文件很大,有时会出现不稳定的行为)。重复相同文件选择的过程通常有效(作为修复)。

非常感谢任何帮助。

使用的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. 此时要上传的文件(图像)有效。接下来吧 检查浏览器是否通过if (typeof window.URL == 'undefined') return;支持File API CreateObjectURL(如果没有,请跳过 接下来的步骤)

  4. 它将图像blob加载到当前图片预览中(使用了一个) 显示当前图像)也可以动态生成 使用jcrop添加到jquery工具覆盖中的图像元素 裁剪功能。

  5. 然后用户通过jcrop裁剪图像并关闭叠加层, 看到要上传的图像的裁剪预览(仅限于 浏览器支持CreateObjectURL,用户裁剪图像)

  6. 守则

    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
            }
        });
    });
    

    随意使用该代码(我对此处收到的任何帮助的贡献)。

    更新

    关于使用JCrop,我遇到了关于stackoverflow的另一个关于类似问题(图像加载然后消失)的问题。我现在打赌JCrop是罪魁祸首。

    我还读过,当img.onload执行时,图像并不总是“准备好”,因此使用setTimeout对.actualWidth / .actualHeight进行奇怪的行为和附加检查可能会解决问题。我会调查一下。

    更新

    我使用FileReader和readAsDataUrl而不是使用CreateObjectURL并使用CANVAS绘制预览而不是基于边距的溢出:隐藏解决方案。需要一些改进然后我会在这里发布代码。

1 个答案:

答案 0 :(得分:2)

在声明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

希望这会有所帮助