Drawing image on canvas in loop not working - javascript

var canvas = document.getElementById("canvas");
wheel = canvas.getContext("2d");
for (var i = 0; i < 10; i++) {
var img = new Image;
img.src = image;
wheel.drawImage(img, -170, -10, 140, 140);
}
My above code draw only 9(Nine) images but lastOne(10th) image not drawing on canvas. I tried above code but not getting success. Anyone can know solution for this problem.
Can any one help me to find out online JSFiddle Demo which draw image on canvas in loop.

Perhaps your image isn't finished loading before your first draw attempt.
Here is the syntax to make sure your image has finished loading:
var canvas = document.body.appendChild(document.createElement("canvas"));
canvas.width = 1100;
canvas.height = 110;
var wheel = canvas.getContext("2d");
var img = document.createElement("img");
img.onload = function() {
for (var i = 0; i < 10; i++) {
wheel.drawImage(img, 5 + 110 * i, 5);
}
};
img.src = "https://placeholdit.imgix.net/~text?txtsize=60&txt=1&w=100&h=100";
EDIT 1 - PROMISES
Working with multiple images:
List sources
map to generates DOM nodes
Setup a Promise per DOM node in a Promise.all
Then draw images
var canvas = document.body.appendChild(document.createElement("canvas"));
canvas.width = 1100;
canvas.height = 110;
var wheel = canvas.getContext("2d");
var images = [
"https://placeholdit.imgix.net/~text?txtsize=60&txt=1&w=100&h=100",
"https://placeholdit.imgix.net/~text?txtsize=60&txt=2&w=100&h=100",
"https://placeholdit.imgix.net/~text?txtsize=60&txt=3&w=100&h=100",
"https://placeholdit.imgix.net/~text?txtsize=60&txt=4&w=100&h=100",
"https://placeholdit.imgix.net/~text?txtsize=60&txt=5&w=100&h=100",
"https://placeholdit.imgix.net/~text?txtsize=60&txt=6&w=100&h=100",
"https://placeholdit.imgix.net/~text?txtsize=60&txt=7&w=100&h=100",
"https://placeholdit.imgix.net/~text?txtsize=60&txt=8&w=100&h=100",
"https://placeholdit.imgix.net/~text?txtsize=60&txt=9&w=100&h=100",
"https://placeholdit.imgix.net/~text?txtsize=60&txt=10&w=100&h=100",
]
.map(function(i) {
var img = document.createElement("img");
img.src = i;
return img;
});
Promise.all(images.map(function(image) {
return new Promise(function(resolve, reject) {
image.onload = resolve;
});
}))
.then(function() {
for (var i = 0; i < images.length; i++) {
var img = images[i];
wheel.drawImage(img, 5 + 110 * i, 5);
}
});

I would do the similar approach to Emil, only difference having a method that loads them individually and once the image is loaded, try to load the next one and so on ...
take a look:
var canvas = document.getElementById("canvas");
// setting canvas size
canvas.height = window.innerHeight - 10;
canvas.width = window.innerWidth - 10;
var image_test = document.querySelector(".hidden");
var count = 0;
var total_images = 10;
var wheel = canvas.getContext("2d");
function loadImage() {
var img = new Image();
img.onload = function() {
wheel.drawImage( this , 105 * count , 0 , 100, 100);
if( count < total_images ) {
count++;
loadImage();
}
}
// img.src = "image-" + count + ".jpg";
img.src = "https://placeholdit.imgix.net/~text?txtsize=60&txt=1&w=100&h=100";
}
loadImage();
https://jsfiddle.net/gugalondon/r5xw6u7L/7

Related

Image concatenation script

everyone. I'm trying to write a script that would render images from file inputs on a canvas in a row.
First I cycle through images to calculate the canvas width (because the canvas is wiped on resizing). Then cycle again to render the images.
canvas.width = 0;
let x = 0,
y = 0,
totalWidth = 0;
for (let i = 0; i < document.querySelectorAll(".has-file").length; i++) {
let input = document.querySelectorAll(".has-file")[i];
let image = input.files[0];
let img = new Image();
console.log(img);
img.src = window.URL.createObjectURL(image);
img.addEventListener('load', () => {
console.log(img);
let newWidth = img.width * canvas.height / img.height;
totalWidth += newWidth;
canvas.width = totalWidth;
}, false);
};
for (let i = 0; i < document.querySelectorAll(".has-file").length; i++) {
let input = document.querySelectorAll(".has-file")[i];
let image = input.files[0];
let img = new Image();
img.src = window.URL.createObjectURL(image);
img.addEventListener('load', () => {
let newWidth = img.width * canvas.height / img.height;
ctx.drawImage(img, x, y, newWidth, canvas.height);
x += newWidth;
}, false);
};
}
The app behaves weird, the images are not always rendered, and when they do, not always where they supposed to be.
First problem with the code is that you're loading images twice, and the randomness is due to the fact that image loading can be ambiguous. Check out this jsfiddle. I have used text input instead of files, drawing takes place when it is the last image otherwise resizing the canvas can cause canvas to reset, losing the previous draw.
var canvas = document.getElementById("canvas");
const ctx = canvas.getContext('2d', {
antialias: false,
depth: false
});
canvas.width = 0;
let x = 0,
y = 0,
totalWidth = 0;
let obj = [];
let k = 0;
for (let i = 0; i < document.querySelectorAll(".has-file").length; i++) {
let input = document.querySelectorAll(".has-file")[i];
let image = input.value;
let img = new Image();
img.src = image;//window.URL.createObjectURL(image);
img.addEventListener('load', () => {
console.log(img);
let newWidth = img.width * canvas.height / img.height;
totalWidth += newWidth;
canvas.width = totalWidth;
obj.push({img: img, x: x, y: y, newWidth: newWidth, height: canvas.height});
k++;
x += newWidth;
if (k == document.querySelectorAll(".has-file").length )
draw();
}, false);
};
function draw() {
for (var i = 0; i < obj.length; i++) {
ctx.drawImage(obj[i].img, obj[i].x, obj[i].y, obj[i].newWidth, obj[i].height);
}
}
<input style="display: none;" class="has-file" value="https://i.imgur.com/I86rTVl.jpg" />
<input style="display: none;" class="has-file" value="https://images.unsplash.com/photo-1446292267125-fecb4ecbf1a5?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=1350&q=80" />
<canvas id="canvas"></canvas>

Filters on images loses when resizing canvas

I have been trying to put filters (like brightness, contrast) on image loaded in canvas.
Below is a snippet of what I am doing
/******Loading Image in Canvas******/
let canvas = document.getElementById('demo');
let ctx = canvas.getContext('2d');
var reader = new FileReader();
reader.onload = function(event){
var img = new Image();
img.onload = function(){
canvas.width = 220;
canvas.height = 250;
ctx.drawImage(img,0,0,canvas.width,canvas.height);
}
img.src = event.target.result;
self.oldImg = event.target.result;
}
reader.readAsDataURL(xevents.target.files[0]);
I have added brightness, contrast logic and is working fine on the image.
The Issue actually arise when I do any operation on image like resizing the canvas(using jquery UI resizeable). The filters applied get lost.
Below is the snippet for redrawing on canvas when resizes.
$(".stretch").resizable({ resize: function(event, ui) {
$("#demo", this).each(function() {
$(this).attr({ width: ui.size.width, height: ui.size.height });
self.reDraw(this);
});
} });
reDraw () {
var img = new Image();
var canvas = document.getElementById('demo');
var c = canvas.getContext("2d");
img.src = this.oldImg;
c.drawImage(img, 0, 0, canvas.width, canvas.height);
}
I believe, since it is creating again a new image object (new Image()), the filters are getting lost.
Can anyone help me on this. I want the filters to be retained as I resize the canvas.
Appreciated !! Thanks
Update
process (type, amount) {
var img = new Image();
var canvas = document.getElementById('demo');
var c = canvas.getContext("2d");
img.src = this.oldImg;
c.drawImage(img, 0, 0, canvas.width, canvas.height);
let imgData = c.getImageData(0, 0, canvas.width, canvas.height);
let data = imgData.data;
if(type === 'b') {
for (let i = 0; i < data.length; i += 4) {
data[i] += amount;
data[i + 1] += amount;
data[i + 2] += amount;
}
}
if(type === 'c') {
amount = (amount/100) + 1; //convert to decimal & shift range: [0..2]
let intercept = 128 * (1 - amount);
for(let i=0;i<data.length;i+=4){ //r,g,b,a
data[i] = data[i]*amount + intercept;
data[i+1] = data[i+1]*amount + intercept;
data[i+2] = data[i+2]*amount + intercept;
}
}
c.putImageData(imgData, 0, 0);
}

Combine two images in one canvas

I am using this code to display data of two canvas into third canvas but it is not working.
I am saving the two canvas data using localstorage and passing it to third canvas
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
//First canvas data
var img1 = loadImage(localStorage.getItem('cbdata'), main);
//Second canvas data
var img2 = loadImage(localStorage.getItem('cbdata1'), main);
var imagesLoaded = 0;
function main() {
imagesLoaded += 1;
if (imagesLoaded == 2) {
// composite now
ctx.drawImage(img1, 0, 0);
ctx.globalAlpha = 0.5;
ctx.drawImage(img2, 0, 0);
}
}
function loadImage(src, onload) {
var img = new Image();
img.onload = onload;
img.src = src;
return img;
}
Your code works. Check that the content of localStorage.getItem is non-empty. And I also slightly modified display of the images by changing ctx.drawImage commands:
var canvas = document.getElementById("canvas");
var ctx = canvas.getContext("2d");
//First canvas data
var img1 = loadImage('http://ep01.epimg.net/elpais/imagenes/2015/10/21/ciencia/1445444934_907402_1445781076_portada_normal.jpg', main);
//Second canvas data
var img2 = loadImage('http://ep01.epimg.net/economia/imagenes/2015/10/22/actualidad/1445508003_507635_1445508894_portada_normal.jpg', main);
var imagesLoaded = 0;
function main() {
imagesLoaded += 1;
if (imagesLoaded == 2) {
// composite now
ctx.drawImage(img1, 0, 0, 100, 100);
ctx.globalAlpha = 0.5;
ctx.drawImage(img2, 100, 0, 100, 100);
}
}
function loadImage(src, onload) {
console.log('loadImage', src);
var img = new Image();
img.onload = onload;
img.src = src;
return img;
}
https://jsfiddle.net/4Le4g8ta/

draw array of images with one onload?

I want draw a line of images with one onload function.
I've tried this code
for(i = 0; i < 8; i++){
var canvas = document.getElementById('ctx');
var context = canvas.getContext("2d");
var imageObj = new Image();
imageObj.src = "thumb.png";
imageObj.setAtX = i * 10;
imageObj.setAtY = i * 10;
imageObj.onload = function() {
context.drawImage(this, this.setAtX, this.setAtY);
};
}
(in java-script)
// put the paths to your images in imageURLs[]
var imageURLs=[];
imageURLs.push("image1.png");
imageURLs.push("image2.png");
// the loaded images will be placed in imgs[]
var imgs=[];
var imagesOK=0;
loadAllImages(start);
function loadAllImages(callback){
for (var i=0; i<imageURLs.length; i++) {
var img = new Image();
imgs.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 imgs[] array now holds fully loaded images
// the imgs[] are in the same order as imageURLs[]
}
Just reuse the image, and when the image has loaded then draw it in a loop - reorganize like this:
var canvas = document.getElementById('ctx');
var context = canvas.getContext("2d");
var imageObj = new Image();
imageObj.onload = function() {
for(var i = 0; i < 8; i++) context.drawImage(this, i * 10, i * 10);
// .. call next step from here
};
imageObj.src = "thumb.png";
Try to avoid setting new properties on native objects. In this case you don't need it, just iterate when the image has loaded.
var imageObj = [];
for(var i=0;i<images.length;i++){
iy = parseInt(i/6) * 200;
ix = parseInt(i%6) * 200;
imageObj[i] = new Image();
imageObj[i].src = images[i];
// to set additinal parameter
imageObj[i].ix = JSON.parse(JSON.stringify(ix));
imageObj[i].iy = JSON.parse(JSON.stringify(iy));
// console.log(imageObj);
imageObj[i].onload = function() {
console.log(this.ix);
console.log(this.iy);
ctx.drawImage(this, this.ix, this.iy, 200, 200);
};
}

Shattering image using canvas

I'm trying to shatter image to pieces using canvas , this is my code :
var image = new Image();
image.src = 'koals.jpg';
image.onload = cutImageUp;
var imagePieces = [];
function cutImageUp() {
for(var x = 0; x < 5; x++) {
for(var y = 0; y < 5; y++) {
var canvas = document.createElement('canvas');
canvas.width = 50+"px";
canvas.height = 50+"px";
var context = canvas.getContext('2d');
context.drawImage(image, x *50, y * 50, 50, 50, 0, 0, 50, 50);
imagePieces.push(canvas.toDataURL());
}
}
var anImageElement = document.getElementById('img');
anImageElement.src = imagePieces[0];
}
the problem is that image is returning "blank image" (a.k.a its not loaded);
Console ain't throwing any error.
I'm opening it as local html file , both image and html document are in the same folder so there shouldn't be problem with toDataURL() not returning data due to image being on another domain.
Your problem is with the 50+"px" for canvas width and height, remove the +"px" part and your good.
From w3Specs:
The canvas element has two attributes to control the size of the coordinate space: width and height. These attributes, when specified, must have values that are valid non-negative integers.
var image = new Image();
image.src = 'koals.jpg';
image.onload = cutImageUp;
var imagePieces = [];
function cutImageUp() {
for(var x = 0; x < 5; x++) {
for(var y = 0; y < 5; y++) {
var canvas = document.createElement('canvas');
canvas.width = 50;
canvas.height = 50;
var context = canvas.getContext('2d');
context.drawImage(image, x *50, y * 50, 50, 50, 0, 0, 50, 50);
imagePieces.push(canvas.toDataURL());
}
}
var anImageElement = document.getElementById('img');
anImageElement.src = imagePieces[0];
}
jsfiddle

Categories

Resources