如何用img.onload返回函数?

时间:2017-06-06 21:24:02

标签: javascript image-processing canvas filereader onload

我目前正在构建一个应用程序,用户可以在其中上传多个图像并同时使用它们。由于某些进程由于大图像文件而表现不佳,我想在用户获取之前调整它们的大小。

在我的resizer()函数中,我尝试使用canvas调整大小。它有效,但是因为' canvas.toDataURL()'在img.onload函数中,我不知道如何返回值并将其解析为handleFiles()函数。

另外......我尝试了一些案例,其中我从handleFiles()获得了一些代码 - 如:

var preview = document.getElementById("img"+count);
var surface = document.getElementById("cubface"+count);
var count = counterImg();
preview.src =  resizer(e.target.result, count);
surface.src = resizer(e.target.result, count);

将它们放在img.onload函数的末尾,如

var preview = document.getElementById("img"+number);
var surface = document.getElementById("cubface"+number);
preview.src = canvas.toDataURL;
surface.src = canvas.toDataURL;

我得到了调整大小,但是我只得到了要处理的循环中的最后一个图像。

所以问题是:

  1. resizer()函数中,如何返回canvas.toDataURL中的img.onload值?

  2. 为什么循环只覆盖最后一个实例而不是每个图像以及如何解决?

  3. 完整代码:

    JavaScript的:

    function resizer(base64, number){
    
        // Max size for thumbnail
        if(typeof(maxWidth) === 'undefined')  maxWidth = 1200;
        if(typeof(maxHeight) === 'undefined')  maxHeight = 1200;
    
        var img = new Image();
        img.src = base64;
    
        // Create and initialize two canvas
        var canvas = document.createElement("canvas");
        var ctx = canvas.getContext("2d");
        var canvasCopy = document.createElement("canvas");
        var copyContext = canvasCopy.getContext("2d");
    
        img.onload = function() {
    
            // Determine new ratio based on max size
            var ratio = 1;
            if (img.width > maxWidth)
                ratio = maxWidth / img.width;
            else if (img.height > maxHeight)
                ratio = maxHeight / img.height;
    
            // Draw original image in second canvas
            canvasCopy.width = img.width;
            canvasCopy.height = img.height;
            copyContext.drawImage(img, 0, 0);
    
            // Copy and resize second canvas to first canvas
            canvas.width = img.width * ratio;
            canvas.height = img.height * ratio;
            ctx.drawImage(canvasCopy, 0, 0, canvasCopy.width, canvasCopy.height, 0, 0, canvas.width, canvas.height);
    
            return canvas.toDataURL();
    
        };
    
        return img.onload;
    
    }
    
    
    function handleFiles(files) {
        for (var i = 0; i < files.length; i++) {
            var file = files[i];
            var count = counterImg();
            var preview = document.getElementById("img"+count);
            var surface = document.getElementById("cubface"+count);
    
            var reader = new FileReader();
            reader.onload =  (function (preview, surface) {
                return function (e) {
                    var newimage = resizer(e.target.result, count);
                    preview.src =  newimage;
                    surface.src = newimage;
                    $('#image-cropper'+count).cropit('imageSrc', e.target.result);
                }
            })(preview, surface);
            reader.readAsDataURL(file);
        }
    }
    

1 个答案:

答案 0 :(得分:1)

变量计数的范围不正确。

在声明函数的时间和使用函数的时间之间会有一段延迟,因此,每次执行都会以相同的值结束。因此jquery选择器将始终返回相同的元素。这解释了为什么只修改了最后一张图像。

这是一个证明执行的小人物。

https://jsfiddle.net/Lc6bngv5/1/

要解决此问题,只需将count传递给封装预览和表面的函数:

    reader.onload =  (function (preview, surface, count) {
        return function (e) {
            var newimage = resizer(e.target.result, count);
            preview.src =  newimage;
            surface.src = newimage;
            $('#image-cropper'+count).cropit('imageSrc', e.target.result);
        }
    })(preview, surface, count);

关于第二个问题:

resize函数返回一个函数。它不返回该函数的结果。为了正确获取URL,我将使用回调函数:

reader.onload =  (function (preview, surface, count) {
    return function (e) {
        var newimage = resizer(e.target.result, count, function(url){
            preview.src =  url;
            surface.src = url;
            $('#image-cropper'+count).cropit('imageSrc', e.target.result);
        });
    }
})(preview, surface, count);

你必须在调整大小时进行以下更改:

function resizer(base64, number, cb){
    ...
    img.onload = function() {
        ...
        // return canvas.toDataURL();
        cb(canvas.toDataURL());
    };
}