I am working on a website that, when loaded, it displays the piled image from an HTML canvas element. My problem is that I can't tell when an image is loaded to draw it to the canvas or how to force an image to be loaded before I proceed to the next step. I have been looking through previous posts about the subject and have tried a lot of different solutions but nothing is working for me.
I am using web2py so I do use some Python helpers which are run on the server side.
When I use this:
canvas = document.getElementById('canvas');
context = canvas.getContext('2d');
image1 = new Image();
image1.src = '{{=URL('static', 'images/image-wrap-border-land.png')}}'; //resolves to: '/SNotes/static/images/image-wrap-border-land.png'
image1.onload = function() {
context.drawImage(image1, 0, 0, canvas.width, canvas.height);
};
Since the image isn't loaded, the onload function doesn't do anything and it skips over it. I have also tried putting the onload function before I set the source but the image still isn't drawn.
I have tried:
//code from above
if(image1pleted) {
context.drawImage(image1, 0, 0, canvas.width, canvas.height);
}
But have faced the same problem.
I have also looked at the possibility that the image is producing an error as it is loaded. To catch this I wrote:
//code from above
image1.onerror = function() {
console.log('error');
}
But the image source is fine, and the image isn't producing an error, it is just taking a long time to load.
Is there a way to wait for an image to load before it is drawn to the canvas?
Edit to add specificity:
My HTML looks like this:
<div id="profile-container" class="container-fluid">
<h1>My Notes</h1>
<div id="empty-orders" class="column-wrapper disable" style="padding-top: 5px; margin: 0 38%;">
<h3>Create a Note and it will appear here</h3>
<button class="btn btn-lg btn-outline">{{=A('GET STARTED', _href=URL('default', 'canvas_board_print'))}}</button>
</div>
<div id="loading" class="column-wrapper">
<i class="fa fa-cog fa-spin fa-3x fa-fw"></i>
</div>
<div id="row1" class="row">
</div>
</div>
My javascript looks like this:
function showOrders(note_orders) {
var orders = note_orders;
//console.log(orders);
var row_num = 1;
var node_num = 1;
if(orders.length > 0) {
for (var i = 0; i != orders.length; i++) {
orders[i].border = JSON.parse(orders[i].border);
orders[i].image_retouching = JSON.parse(orders[i].image_retouching);
orders[i].shipping_info = JSON.parse(orders[i].shipping_info);
var new_node = $("<div>", {id: "node" + node_num, "class": "col-xs-3 node-wrapper"});
var new_canvas = $('<canvas>', {id: "canvas" + node_num, style: 'display: none'});
var new_image = $('<img>', {id: "note_prev" + node_num, 'class': 'img-responsive'});
$('#row' + row_num).append(new_node);
$('#node'+ node_num).append(new_canvas).append(new_image).append(processOrders(orders[i], node_num));
node_num++;
if (i != 0 && (i + 1) % 4 == 0) {
row_num++;
var new_row = $("<div>", {id: "row" + row_num, "class": "row"});
$(' #profile-container ').append(new_row);
}
}
$(' #loading ').addClass('disable');
} else {
$(' #loading ').addClass('disable');
$(' #empty-orders ').removeClass('disable');
}
}
function processOrders(curr_order, node_num) {
var canvas = document.getElementById('canvas' + node_num);
var context = canvas.getContext('2d');
var image1 = new Image();
image1.src = curr_order.image_url;
canvas.width = image1.naturalWidth;
canvas.height = image1.naturalHeight;
if(image1plete) {
context.drawImage(image1, 0, 0, canvas.width, canvas.height);
if(curr_order.border.style == 'color_wrap') {
document.getElementById('note_prev' + node_num).style.border = "10px solid " + curr_order.border.color;
} else if(curr_order.border.style == 'image_wrap') {
var image_wrap = new Image();
if(canvas.width > canvas.height) {
image_wrap.src = '{{=URL('static', 'images/image-wrap-border-land.png')}}';
} else {
image_wrap.src = '{{=URL('static', 'images/image-wrap-border-port.png')}}';
}
console.log(image_wrap);
image_wrap.onload = function() {
context.drawImage(image_wrap, 0, 0, canvas.width, canvas.height);
};
image_wrap.onerror = function() {
console.log('errors');
}
}
}
document.getElementById('note_prev' + node_num).src = canvas.toDataURL('image/png');
var node_div = document.createElement('div');
//Other non-image informantion is appended to node_div
return node_div;
}
My problem is when drawing image_wrap, not image1 from my above example. Image1 from my code draws fine, but image_wrap won't appear when it is drawn to the canvas.
I FIXED IT!!!
I moved the creation of image_Wrap variable up with the creation of the image1 variable.
function processOrders(curr_order, node_num) {
var canvas = document.getElementById('canvas' + node_num);
var context = canvas.getContext('2d');
var image1 = new Image();
var image_wrap = new Image();
image1.src = curr_order.image_url;
canvas.width = image1.naturalWidth;
canvas.height = image1.naturalHeight;
if(image1plete) {
context.drawImage(image
I thought this wouldn't be a good idea because I didn't want to create extra variables even if they weren't going to get used, but I guess it fixed it.
I am working on a website that, when loaded, it displays the piled image from an HTML canvas element. My problem is that I can't tell when an image is loaded to draw it to the canvas or how to force an image to be loaded before I proceed to the next step. I have been looking through previous posts about the subject and have tried a lot of different solutions but nothing is working for me.
I am using web2py so I do use some Python helpers which are run on the server side.
When I use this:
canvas = document.getElementById('canvas');
context = canvas.getContext('2d');
image1 = new Image();
image1.src = '{{=URL('static', 'images/image-wrap-border-land.png')}}'; //resolves to: '/SNotes/static/images/image-wrap-border-land.png'
image1.onload = function() {
context.drawImage(image1, 0, 0, canvas.width, canvas.height);
};
Since the image isn't loaded, the onload function doesn't do anything and it skips over it. I have also tried putting the onload function before I set the source but the image still isn't drawn.
I have tried:
//code from above
if(image1.pleted) {
context.drawImage(image1, 0, 0, canvas.width, canvas.height);
}
But have faced the same problem.
I have also looked at the possibility that the image is producing an error as it is loaded. To catch this I wrote:
//code from above
image1.onerror = function() {
console.log('error');
}
But the image source is fine, and the image isn't producing an error, it is just taking a long time to load.
Is there a way to wait for an image to load before it is drawn to the canvas?
Edit to add specificity:
My HTML looks like this:
<div id="profile-container" class="container-fluid">
<h1>My Notes</h1>
<div id="empty-orders" class="column-wrapper disable" style="padding-top: 5px; margin: 0 38%;">
<h3>Create a Note and it will appear here</h3>
<button class="btn btn-lg btn-outline">{{=A('GET STARTED', _href=URL('default', 'canvas_board_print'))}}</button>
</div>
<div id="loading" class="column-wrapper">
<i class="fa fa-cog fa-spin fa-3x fa-fw"></i>
</div>
<div id="row1" class="row">
</div>
</div>
My javascript looks like this:
function showOrders(note_orders) {
var orders = note_orders;
//console.log(orders);
var row_num = 1;
var node_num = 1;
if(orders.length > 0) {
for (var i = 0; i != orders.length; i++) {
orders[i].border = JSON.parse(orders[i].border);
orders[i].image_retouching = JSON.parse(orders[i].image_retouching);
orders[i].shipping_info = JSON.parse(orders[i].shipping_info);
var new_node = $("<div>", {id: "node" + node_num, "class": "col-xs-3 node-wrapper"});
var new_canvas = $('<canvas>', {id: "canvas" + node_num, style: 'display: none'});
var new_image = $('<img>', {id: "note_prev" + node_num, 'class': 'img-responsive'});
$('#row' + row_num).append(new_node);
$('#node'+ node_num).append(new_canvas).append(new_image).append(processOrders(orders[i], node_num));
node_num++;
if (i != 0 && (i + 1) % 4 == 0) {
row_num++;
var new_row = $("<div>", {id: "row" + row_num, "class": "row"});
$(' #profile-container ').append(new_row);
}
}
$(' #loading ').addClass('disable');
} else {
$(' #loading ').addClass('disable');
$(' #empty-orders ').removeClass('disable');
}
}
function processOrders(curr_order, node_num) {
var canvas = document.getElementById('canvas' + node_num);
var context = canvas.getContext('2d');
var image1 = new Image();
image1.src = curr_order.image_url;
canvas.width = image1.naturalWidth;
canvas.height = image1.naturalHeight;
if(image1.plete) {
context.drawImage(image1, 0, 0, canvas.width, canvas.height);
if(curr_order.border.style == 'color_wrap') {
document.getElementById('note_prev' + node_num).style.border = "10px solid " + curr_order.border.color;
} else if(curr_order.border.style == 'image_wrap') {
var image_wrap = new Image();
if(canvas.width > canvas.height) {
image_wrap.src = '{{=URL('static', 'images/image-wrap-border-land.png')}}';
} else {
image_wrap.src = '{{=URL('static', 'images/image-wrap-border-port.png')}}';
}
console.log(image_wrap);
image_wrap.onload = function() {
context.drawImage(image_wrap, 0, 0, canvas.width, canvas.height);
};
image_wrap.onerror = function() {
console.log('errors');
}
}
}
document.getElementById('note_prev' + node_num).src = canvas.toDataURL('image/png');
var node_div = document.createElement('div');
//Other non-image informantion is appended to node_div
return node_div;
}
My problem is when drawing image_wrap, not image1 from my above example. Image1 from my code draws fine, but image_wrap won't appear when it is drawn to the canvas.
I FIXED IT!!!
I moved the creation of image_Wrap variable up with the creation of the image1 variable.
function processOrders(curr_order, node_num) {
var canvas = document.getElementById('canvas' + node_num);
var context = canvas.getContext('2d');
var image1 = new Image();
var image_wrap = new Image();
image1.src = curr_order.image_url;
canvas.width = image1.naturalWidth;
canvas.height = image1.naturalHeight;
if(image1.plete) {
context.drawImage(image
I thought this wouldn't be a good idea because I didn't want to create extra variables even if they weren't going to get used, but I guess it fixed it.
Share Improve this question edited Aug 10, 2016 at 1:37 nightwuffle asked Aug 10, 2016 at 0:06 nightwufflenightwuffle 3415 silver badges12 bronze badges 03 Answers
Reset to default 4I was able to load the image using your code.
Can you confirm you are not getting an error while loading the image?
(Seeking clarification: posted as an answer to demo the running code snippet)
Update: added a hackish way to wait a second after loading image and before drawing it to canvas
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
var image1 = new Image();
image1.src = 'http://lorempixel./400/200/sports/1/';
image1.onload = function() {
// you could draw the image right away
// ctx.drawImage(image1, 0, 0, canvas.width, canvas.height);
// OR
// You could wait for an extra second before drawing the image (hackish, I know)
setTimeout(function() {
ctx.drawImage(image1, 0, 0, canvas.width, canvas.height);
}, 1 * 1000); // 1 second (in milliseconds)
};
<h2>canvas</h2>
<canvas id='canvas'>
</canvas>
<hr/>
Set the onload function BEFORE you set the src. It's likely that the image is loading before the onload function is being set.
canvas = document.getElementById('canvas');
context = canvas.getContext('2d');
image1 = new Image();
image1.onload = function() {
context.drawImage(image1, 0, 0, canvas.width, canvas.height);
};
image1.src = '{{=URL('static', 'images/image-wrap-border-land.png')}}'; //resolves to: '/SNotes/static/images/image-wrap-border-land.png'
The first parameter for context.drawImage is the image you want to draw, the second two are the position on the context....
context.drawImage(img,sx,sy,swidth,sheight,x,y,width,height);
The remaining parameters allow you to scale the image.
Suggest you try..
image1.onload = function() { context.drawImage(image1,0,0); }