zwwcn

Just another WordPress.com site

Multiple Canvas only draw the last one

I have five canvas on the page, The following code is supposed to read the image data from hidden input field and draw image to the correspoding canvas. but it only draw the last one.

$('.signatureField').each(function() {					   
	if($(this).children("input").val()!=""){
		canvas = $(this).children('canvas').get(0);
		ctx = canvas.getContext('2d');
		testImage = new Image();

		testImage.onload=function(){				
			ctx.drawImage(testImage,0,0,testImage.width,testImage.height,0,0,canvas.width,canvas.height);
		}
						
		testImage.src="data:image/png;base64,"+$(this).children("input").val();
	}						
})

Adding “var” to ctx solves the problem.What that does is to declare ctx as local variable in each loop, so they don’t share the same convas context.

$('.signatureField').each(function() {					   
	if($(this).children("input").val()!=""){
		var canvas = $(this).children('canvas').get(0);
		var ctx = canvas.getContext('2d');
		var testImage = new Image();

		testImage.onload=function(){				
			ctx.drawImage(testImage,0,0,testImage.width,testImage.height,0,0,canvas.width,canvas.height);
		}
						
		testImage.src="data:image/png;base64,"+$(this).children("input").val();
	}
})

Then I have the following code in CoffeeScript, unfortunately, it only draw the last canvas. Here I use apostrophe to declare canvas context as local variable. Also added an empty return at the end of the function to avoid CoffeeScript implicit return.

checklist.loadExistingSignature = (fields) ->
    for field in fields
        if field.type='signature' and field.value.length>0
            `var fieldCanvas = $('#' + field.id).get(0)`
            `var canvastx = fieldCanvas.getContext('2d')`
            `var testImage = new Image()`
            
            testImage.onload = ->
            	canvastx.drawImage(testImage,0,0,testImage.width,testImage.height,0,0,fieldCanvas.width,fieldCanvas.height);
            	return
            testImage.src = "data:image/png;base64," + field.value;
    return

To solve this problem, we need to add a javascript closure. In CoffeeScript , it’s the do function

checklist.loadExistingSignature = (fields) ->
    for field in fields
        if field.type='signature' and field.value.length>0
            `var fieldCanvas = $('#' + field.id).get(0)`
            `var canvastx = fieldCanvas.getContext('2d')`
            `var testImage = new Image()`
            do (canvastx, testImage) ->
            	testImage.onload = ->
            		canvastx.drawImage(testImage,0,0,testImage.width,testImage.height,0,0,fieldCanvas.width,fieldCanvas.height);
            		return
            	return
            testImage.src = "data:image/png;base64," + field.value;
    return

And the javascript version:

for (var i = 1; i < 5; i++) {
    var ctx = document.getElementById('canvas-' + i).getContext('2d'),
        image = new Image();
    (function(ctx, image) {
        image.onload = function() {
            ctx.drawImage(image, 0, 0);
        }
        image.src = images[(i - 1)];
    })(ctx, image);
}

ref for javascript closure in loop: http://www.mennovanslooten.nl/blog/post/62

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: