2015-12-03 20 views
0

我想创建一个图像条并组成一个新图像,如image = [image0-image1-image2]。将图像数组与javascript(有或没有画布)结合使用

我们将使用:

images = ['https://upload.wikimedia.org/wikipedia/commons/5/55/Al-Farabi.jpg', 
    'https://upload.wikimedia.org/wikipedia/commons/e/e1/FullMoon2010.jpg', 
'https://upload.wikimedia.org/wikipedia/commons/thumb/2/2c/3D_coordinate_system.svg/10000px-3D_coordinate_system.svg.png'] 

我想借外上方,使拼贴。 我想在背景中做到这一点。

我了解到,可以使用关闭的画布元素;为了看我在做什么,我会在这里使用一个画布元素。

// create an off-screen canvas using document.createElement('canvas') 
// here I use a canvas in DOM cause I cannot find a way to displayed the final collage 
var canvas = document.getElementById('canvas'), 
    context = canvas.getContext('2d'); 

// set its dimension to target size 
canvas.width = 1200; 
canvas.height = 630; 

并发现三种不同的行为,我认为应该给出相同的结果。你能解释我为什么吗?

如果我手动复制并在控制台代码粘贴对于每个图像,一次一个timeenter代码here`

var image = new Image(); 
// i is the i-th element in images 
image.src = images[i]; 
image.onload = function() { 
    context.save(); 
    context.drawImage(image, canvas.width * 0.3 * i, 0, canvas.width*0.3, canvas.height); 
} 

我可以看到元件定位一个预留其他的,如我想有。

但如果我在一次复制所有的三块代码,无论是在一个循环,我只能看到最后一个图像置于在三个不同位置的所有

for (var i = images.length; i <= 0; i++) { 
var image = new Image(); 
image.src = images[i]; 
    image.onload = function(){ 
     context.save(); 
     context.drawImage(image, canvas.width*0.3 * i, 0, canvas.width*0.3, canvas.height); 
    } 
} 

所以我想,也许这是在图像加载后使用回调的问题 - 我尝试了以下方法,但没有任何反应:canvas保持空白。

// my callback 
function addImage(image, position){ 
     image.onload = function(){ 
      context.save(); 
      context.drawImage(image, canvas.width*0.3 * position, 0, canvas.width*0.3, canvas.height); 
     }   
} 

function loadImages (images, callback) { 
    for (var i = images.length-1; i >= 0; i--) { 
    var image = new Image(); 
    image.src = images[i]; 
    callback(image, i); 
    } 
} 


// canvas will stay empty: 
loadImages(images, addImage); 

你能帮助澄清三部分的差异,并弄清楚如何将一个图像数组合在一起?

可能在后台,我想要保存图像并通过ajax发布。

回答

1

在你的循环例子中,所有的onload函数都在循环中共享相同的i和image变量。但是onload函数是循环完成后调用的回调函数。因此,所有的onload函数都在循环完成后使用相同的i和图像值。您需要创建一个本地范围,以便每个onload函数都有它自己的i和图像值。例如...

for (var i = 0; i < images.length; i++) { 
    var image = new Image(); 
    image.src = images[i]; 
    image.onload = function(image, i) { 
     return function(){ 
      context.drawImage(image, canvas.width*0.3 * i, 0, canvas.width*0.3, canvas.height); 
     } 
    }(image, i); 
} 
+0

谢谢@bobby为您解释!你引入了一个局部作用域:本地作用域与回调函数不同的方式是什么? (我指的是我的尝试#3)。你能解释一下回调('image.onload')结尾的语法'(image,i)'是什么意思?更一般地说,这种技术何时用于回调或承诺? – user305883

+1

onload = function(image,i){...}(image,i)语法创建并立即调用匿名函数。循环的图像和i变量的值被传递给匿名函数并存储在匿名函数的作用域中。匿名函数然后创建并返回第二个匿名函数,该函数被分配为onload回调函数。第二个匿名函数将使用来自第一个匿名函数范围的图像和i值。这导致每个onload回调函数都有自己的图像和i值。 –

+1

谷歌搜索“javascript闭包范围”将返回大量文章,提供更全面的描述这种方法。例如:https://developer.mozilla。org/en-US/docs/Web/JavaScript/Closures –