zwwcn

Just another WordPress.com site

Category Archives: coffescript

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