how to draw multiple images in canvas - javascript

I need to draw images in their own canvas. What am I doing wrong?
If I delete the "for loop" the code works just fine (e.g: set var i=0, then img[0] is drawn in canv[0]).
window.onload = function() {
var canv = [];
var ctx = [];
var img = [];
var info = [{"url":"1.jpg"},{"url":"2.jpg"},{"url":"3.jpg"}];
for(i=0; i< 3; i++){
canv[i] = document.createElement('canvas');
canv[i].width = 460;
canv[i].height = 620;
canv[i].style.border = "1px solid";
document.body.appendChild(canv[i]);
img[i] = new Image();
img[i].src = info[i].url;
ctx[i] = canv[i].getContext("2d");
img[i].onload = function(){
ctx[i].drawImage(img[i], 10, 70, 440,440);
}
}
}

Found the solution, just in case somebody has the same problem:
(function (_i) {
img[_i] = new Image();
img[_i].src = info[_i].url;
img[_i].onload = function () {
ctx[_i].drawImage(img[_i], 10, 70, 440,440);
};
})(i);

Related

Refresh the image without reloading the page

Each new image should be with different src. Untill reloading all images have single src. It is can be add location.reload(); until adding new image, then scr will change. But reloading very seen. Does it exist way to reload only scr?
var cvs;
var ctx;
cvs = document.getElementById("canvas");
ctx = cvs.getContext("2d");
var width_path_near = 80,
width_path_far = 30;
var tree1 = new Image();
var tree2 = new Image();
var tree3 = new Image();
var tree4 = new Image();
tree1.src = "https://png.pngtree.com/element_origin_min_pic/00/02/61/6156839a2a633b7.jpg";
tree2.src = "http://s02.yapfiles.ru/files/457732/derevo_1.png";
tree3.src = "http://www.grafamania.net/uploads/posts/2014-06/1401644723_1-9.jpg";
tree4.src = "http://img11.txapela.ru/e/c/c/4/f/52e052f118c7b8ff9317385f581.jpg";
var masTree=[tree1, tree2, tree3, tree4];
var randTree=Math.floor(Math.random()*masTree.length);
var tree_size = 100;
var grow = 0.2;
var gap = 100;
var forest = [];
forest[0] = {
x : cvs.width/2-width_path_near-tree_size/2,
y : cvs.height/2-tree_size+10,
size : tree_size
}
function draw() {
ctx.fillStyle = "rgb(84,209,216)";
ctx.fillRect(0, 0, 1000, 600);
for (var i=0; i<forest.length; i++){
ctx.drawImage(masTree[randTree], forest[i].x, forest[i].y, forest[i].size, forest[i].size);
if(forest[i].y == 3*cvs.height/4){
forest.push({
y : cvs.height/2-tree_size+10,
x : cvs.width/2-width_path_near-tree_size/2,
size : tree_size
});
}
forest[i].y += 0.5;
forest[i].x -= 0.4;
forest[i].size += 0.4;
}
requestAnimationFrame(draw);
}
masTree[randTree].onload = draw;
http://jsfiddle.net/Nata_Hamster/ugyb1fd0/

Images not loaded on first call in html canvas

I want to load the sorted array images in canvas in a same sequence, for that i created a load function and I am calling it from there.
Every thing works fine, but the problem is that it does not draw the images on canvas at first call.
Here is a fiddle
With my current code, it does not show you an image , but when you run it again, it will create and show the canvas image.
I am facing the same issue in my local host where i load the images with ajax.
var ImagesArray = new Array("http://s4.postimg.org/dw8aujkkd/slim_Fit.png",
"http://s27.postimg.org/l6mq3hboz/outer_collar1.png",
"http://s22.postimg.org/e7alkm44x/inner_collar11.png",
"http://s12.postimg.org/h4kgdjn4t/maincolar.png",
"http://s13.postimg.org/edabwknfr/outer_fastening1.png");
//alert(ImagesArray.length);
MainMethods(ImagesArray);
function MainMethods(responseImages) {
//alert(responseImages.length);
var canvas = document.getElementById("product-image");
canvas.height = ($(window).height()) - 120;
canvas.width = canvas.height * 0.75;
var heightscreen = ($(window).height()) - 120;
var canvasheight = heightscreen;
var canvaswidth = canvas.height * 0.75;
canvaswidthdiv4 = 0;
var widthNeeded = canvasheight * 0.75;
var context = canvas.getContext('2d');
var returnedImages = loadImages(responseImages);
for (i = 0; i < returnedImages.length; i++) {
console.log(returnedImages[i]);
context.drawImage(returnedImages[i], canvaswidthdiv4, 55, widthNeeded, canvasheight);
}
// Image loading global variables
var loadcount = 0;
var loadtotal = 0;
var preloaded = false;
// Load images
function loadImages(imagefiles) {
// Initialize variables
loadcount = 0;
loadtotal = imagefiles.length;
preloaded = false;
// Load the images
var loadedimages = [];
for (var i = 0; i < imagefiles.length; i++) {
// Create the image object
var image = new Image();
// Add onload event handler
image.onload = function() {
loadcount++;
if (loadcount == loadtotal) {
// Done loading
preloaded = true;
}
};
// Set the source url of the image
image.src = imagefiles[i];
// Save to the image array
loadedimages[i] = image;
}
// Return an array of images
return loadedimages;
}
}
<canvas id="product-image" width="700" height="823"></canvas>
The problem is that your images are not loaded yet when you try to draw it.
Wrap the drawImage part in a function and call it when preloaded becomes true, here your boolean does nothing.
I refactored your code a little bit, you also had an issue with loadtotal being reset to 0 after your call to loadImage() function. So loadcountwon't ever be === loadtotal and your useless preloaded never switched to true.
var ImagesArray = new Array ("http://s4.postimg.org/dw8aujkkd/slim_Fit.png",
"http://s27.postimg.org/l6mq3hboz/outer_collar1.png",
"http://s22.postimg.org/e7alkm44x/inner_collar11.png",
"http://s12.postimg.org/h4kgdjn4t/maincolar.png",
"http://s13.postimg.org/edabwknfr/outer_fastening1.png");
function MainMethods(responseImages) {
var canvas = document.getElementById("product-image");
canvas.height = ($(window).height()) - 120;
canvas.width = canvas.height * 0.75;
var canvasheight = ($(window).height()) - 120;
var canvaswidth = canvas.height * 0.75;
canvaswidthdiv4 = 0;
var widthNeeded = canvasheight * 0.75;
var context = canvas.getContext('2d');
// an other error, if you set loadtotal to 0 after calling loadImages(), it will be set to 0 when images are loaded.
// and loadcount won't ever be === loadtotal.
var loadcount;
var loadtotal;
function loadImages(imagefiles) {
loadcount = 0;
loadtotal = imagefiles.length;
var loadedimages = [];
for (var i=0; i<imagefiles.length; i++) {
var image = new Image();
image.onload = function () {
loadcount++;
console.log(loadcount+'/'+ loadtotal);
if (loadcount == loadtotal) {
// done loading all the images
draw(loadedimages);
}
};
image.src = imagefiles[i];
loadedimages[i] = image;
}
}
// Wrap your drawing in a function that will be called asynchronously
function draw(loadedimages){
for (var i = 0; i < loadedimages.length; i++) {
console.log(loadedimages[i]);
context.drawImage(loadedimages[i], canvaswidthdiv4, 55, widthNeeded, canvasheight);
}
}
// Once all your variables are set, you can load the images
loadImages(responseImages);
}
MainMethods(ImagesArray);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<canvas id="product-image"></canvas>
Since it appears to be a browser specific issue, here's a hack to get it to work:
Replace : MainMethods(ImagesArray);
with : setTimeout(function () { MainMethods(ImagesArray); }, 0);
With timeout set to 0 ms, it would virtually execute instantaneously.
JsFiddle : http://jsfiddle.net/wdfrrayh/3/
Tested on IE, FF, Chrome
image src needs to be called after drawImage which i was doing before I have updated my function which is working fine,
below is working code for this
function loadImages(sources, callback, jsondata) {
var images = {};
var loadedImages = 0;
var numImages = 0;
// get num of sources
for(var src in sources) {
numImages++;
}
for(var src in sources) {
images[src] = new Image();
images[src].onload = function() {
if(++loadedImages >= numImages) {
callback(images);
}
};
images[src].src = sources[src];
}
}
var canvas = document.getElementById('product-image');
canvas.height = (jQuery(window).height()) -120;
canvas.width = canvas.height * 0.75;
var heightscreen = (jQuery(window).height()) -120;
var canvasheight = heightscreen;
var canvaswidth = canvas.height * 0.75;
canvaswidthdiv4 = 0;
var widthNeeded = canvasheight * 0.75;
var context = canvas.getContext('2d');
var sources = new Array ("http://s4.postimg.org/dw8aujkkd/slim_Fit.png",
"http://s27.postimg.org/l6mq3hboz/outer_collar1.png",
"http://s22.postimg.org/e7alkm44x/inner_collar11.png",
"http://s12.postimg.org/h4kgdjn4t/maincolar.png",
"http://s13.postimg.org/edabwknfr/outer_fastening1.png");
loadImages(sources, function(images) {
for(var i=0; i < sources.length; i++){
context.drawImage(images[i], canvaswidthdiv4, 55,widthNeeded,canvasheight);
}
});

draw array of images to the canvas

I am trying to draw an array of images to the canvas element, my data:image is returning an empty image.
var imgArray = ['images/image1.png','images/image2.png'];
for(i = 0; i < 2; i++){
var canvas = document.getElementById('textCanvas');
var context = canvas.getContext("2d");
var imageObj = new Image();
imageObj.setAtX = i * 10;
imageObj.setAtY = i * 10;
imageObj.onload = function() {
context.drawImage(this, this.setAtX, this.setAtY);
};
}
img = canvas.toDataURL("image/png");
You never set the images' source:
var imageObj = new Image();
imageObj.src = imgArray[i]; // << addeed
imageObj.setAtX = i * 10;
imageObj.setAtY = i * 10;
imageObj.onload = function() {
context.drawImage(this, this.setAtX, this.setAtY);
};

Canvas patterned pie chart with array image

I am trying to make a pie chart made by patterns using some images. But I can't see any images which I am trying to show. What is the problem with the following codes?
<html>
<body>
<canvas width="250" height="250" id="canvas"></canvas>
<script>
var imgArray = new Array();
imgArray[0] = new Image();
imgArray[0].src = 'p2.jpg';
imgArray[1] = new Image();
imgArray[1].src = 'p3.jpg';
imgArray[2] = new Image();
imgArray[2].src = 'p4.jpg';
imgArray[3] = new Image();
imgArray[3].src = 'p5.jpg';
imgArray[4] = new Image();
imgArray[4].src = 'p6.jpg';
//initialize data set
var data = [ 100, 68, 20, 30, 100 ];
var canvas = document.getElementById('canvas');
var c = canvas.getContext('2d');
//draw background
c.fillStyle = "white";
c.fillRect(0,0,500,500);
//a list of colors
//calculate total of all data
var total = 0;
for(var i=0; i<data.length; i++) {
total += data[i];
}
var prevAngle = 0;
for(var i=0; i<data.length; i++) {
//fraction that this pieslice represents
var fraction = data[i]/total;
In this step, I dynamically try to put the images into the pie chart, but I think the 'src' usage is wrong.
//calc starting angle
var angle = prevAngle + fraction*Math.PI*2;
var pat=c.createPattern(imgArray[i].src,"repeat");
//draw the pie slice
//create a path
c.beginPath();
c.moveTo(250,250);
c.arc(250,250, 100, prevAngle, angle, false);
c.lineTo(250,250);
c.closePath();
//fill it
c.fillStyle = pat;
c.fill();
//stroke it
c.strokeStyle = "black";
c.stroke();
//update for next time through the loop
prevAngle = angle; </script> </body> </html>
You are correct in your suspicion.
createPattern takes an image object--not a URL.
var pat;
var img=new Image();
img.onload=function(){
pat=c.createPattern(img,"repeat");
// now you can create a path and fill it with `pat`
}
img.src="http://whatever.com/whatever.png";
[ Added image loader code in response to additional question ]
// image loader
var imageURLs=[]; // put the paths to your images here
var imagesOK=0;
var imgArray=[];
imageURLs.push("p2.jpg");
imageURLs.push("p3.jpg");
imageURLs.push("p4.jpg");
imageURLs.push("p5.jpg");
imageURLs.push("p6.jpg");
loadAllImages(start);
function loadAllImages(callback){
for (var i=0; i<imageURLs.length; i++) {
var img = new Image();
imgArray.push(img);
img.onload = function(){
imagesOK++;
if (imagesOK>=imageURLs.length ) {
callback();
}
};
img.onerror=function(){alert("image load failed");}
img.crossOrigin="anonymous";
img.src = imageURLs[i];
}
}
function start(){
// the imgArray[] array now holds fully loaded images
// the imgArray[] are in the same order as imageURLs[]
// imgArray[0] is p2.jpg
// imgArray[1] is p3.jpg
// imgArray[2] is p4.jpg
// imgArray[3] is p5.jpg
// imgArray[4] is p6.jpg
// create your patterns now
}

javascript firefox throws operation is insecure error

I'm trying to resize an uploaded image, set it back to the input element before submitting.
$("#upload_button").click(function(){
var imgToUpload = document.getElementById('id_picture').files;
for (var x = 0; x < imgToUpload.length; x ++){
var getImg = imgToUpload[x];
console.log(typeof getImg);
if (! imgToUpload[x].type.match(/image.*/)){
alert("not an image");
return false;
}
var img = document.createElement("img");
img.src = window.URL.createObjectURL(getImg);
var canvas = document.createElement("canvas");
canvas.width = 20;
canvas.height = 20;
var ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0, 20, 20);
var resizedUrl = canvas.toDataURL("image/jpeg",0.7);
var byteString = atob(resizedUrl.split(",")[1]);
var ab = new ArrayBuffer(byteString.length);
var ia = new Uint8Array(ab);
for (var index = 0; index < byteString.length; index++){
ia[index] = byteString.charCodeAt(index);
}
var bob = new Blob([ab], {"type": getImg.type});
var p = document.getElementById('id_picture');
p.value = bob;
$("#upload_form").submit();
}
});
when i reach the p.value = bob, i will encounter the mentioned problem. Am i doing it wrong?
(i read that i can simply use canvas.toDataURL and set it to another hidden input, but I'm trying to see if this is possible)
You can use toDataURL
var canvas = document.getElementById("ex1");
var dataUrl = canvas.toDataURL();
Client example: http://tutorials.jenkov.com/html5-canvas/todataurl.html
Server(PHP) example http://html5stars.com/?p=99

Categories