【问题标题】:load image inside JavaScript function在 JavaScript 函数中加载图像
【发布时间】:2015-04-08 23:06:31
【问题描述】:

我有获取图像像素颜色的功能

function getImage(imgsrc){
    var img = $( "<img>", {
        src: imgsrc
    });
    var imageMap = new Object();
    img.load(function() {
        var canvas = $('<canvas/>')[0].getContext('2d');
        canvas.width = this.width;
        canvas.height = this.height;
        canvas.drawImage(this, 0, 0, this.width, this.height);
        for(var i = 0;i < this.width;i++){
            imageMap[i] = new Object();
            for(var j = 0;j < this.width;j++){
                var pixelData = canvas.getImageData(i, j, 1, 1).data;
                imageMap[i][j] = rgbToHex(pixelData[0],pixelData[1],pixelData[2]);
            }
        }
            console.log(imageMap[40][40]);
    });
    console.log(imageMap[40][40]);
    return imageMap;
}

但它返回未定义(它首先打印第二个 console.log) 怎么了?

谢谢。

【问题讨论】:

  • 这是因为 load 是异步的。你不能通过异步调用return

标签: javascript image function canvas html5-canvas


【解决方案1】:

您的函数正在返回 undefined,因为 load 是异步的。 getImage 正在尝试在 load 完成加载之前返回一些内容。

您需要在图像加载后将回调传递给getImage

function getImage(imgsrc, callback){
    var img = $( "<img>", {
        src: imgsrc
    });
    var imageMap = new Object();
    img.load(function() {
        var canvas = $('<canvas/>')[0].getContext('2d');
        canvas.width = this.width;
        canvas.height = this.height;
        canvas.drawImage(this, 0, 0, this.width, this.height);
        for(var i = 0;i < this.width;i++){
            imageMap[i] = new Object();
            for(var j = 0;j < this.width;j++){
                var pixelData = canvas.getImageData(i, j, 1, 1).data;
                imageMap[i][j] = rgbToHex(pixelData[0],pixelData[1],pixelData[2]);
            }
        }
        console.log(imageMap[40][40]);
        callback(imageMap)
    });
}

然后你只需像这样调用函数:

getImage("http://some.src.jpg", function(imageMap){
    // Do stuff with imageMap here;
});

当然,你也可以在别处定义回调:

var myCallback = function(imageMap){
    // Do stuff with imageMap here;
};

getImage("http://some.src.jpg", myCallback);

【讨论】:

    【解决方案2】:

    jQuery.load() 是异步的,这意味着代码将继续工作,同时它会继续工作。

    如果您想处理imagemap,一种选择可能是传递一个您执行的回调,其中填充了imagemap,类似于:

    function yourCallback(imageMap){
    // ...process imageMap;
    }
    
    function getImage(imgsrc, yourCallback) {
        var img = $("<img>", {
            src: imgsrc
        });
        var imageMap = new Object();
        img.load(function () {
            var canvas = $('<canvas/>')[0].getContext('2d');
            canvas.width = this.width;
            canvas.height = this.height;
            canvas.drawImage(this, 0, 0, this.width, this.height);
    
            for (var i = 0; i < this.width; i++) {
                imageMap[i] = new Object();
                for (var j = 0; j < this.width; j++) {
                    var pixelData = canvas.getImageData(i, j, 1, 1).data;
                    imageMap[i][j] = rgbToHex(pixelData[0], pixelData[1], pixelData[2]);
                }
            }
    
            yourCallback(imageMap);
        });
    }
    
    getImage(imgsrc,yourCallback);
    

    【讨论】:

      【解决方案3】:

      现在承诺 开始获得 [拥有] 广泛的支持,您可以改为这样做:

      // Define a common load function:
      function loadImage(url) {
        return new Promise(function(resolve, reject) {
          var img = new Image;
          img.onload = function() { resolve(this) };
          img.onerror = img.onabort = function() { reject("Error loading image") };
          img.src = url;
        })
      }
      
      // Usage:
      loadImage("https://i.stack.imgur.com/ynBVu.gif").then(function(image) {
      
        // Use the `image` here
        document.body.appendChild(image);
      
      })

      Promise 将在内部接受回调、状态等。 IE 将在下一个版本中获得支持(存在polyfill)。

      【讨论】:

      • 这是目前最准确的答案,因为当前所有浏览器support Promises
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-08-21
      • 2014-11-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多