drawing images on canvas each at random x and y - javascript

guys i want to draw 4 images on canvas but each one at random x and y .. here is my code
var imgs = [];
var fruits = ["fruit1.png", "fruit2.png", "fruit3.png", "fruit4.png"];
var monsterReady1 = false;
for (var i = 0; i < fruits.length; i++) {
imgs[i] = new Image();
imgs[i].onload = function() {
monsterReady1 = true;
};
imgs[i].src = fruits[i];
}
var monsterXY1 = function() {
monster1.x = (Math.random() * (canvas.width - 100));
monster1.y = (Math.random() * (canvas.height - 100));
};
var draw = function() {
if (monsterReady1) {
for (var i = 0; i < fruits.length; i++) {
ctx.drawImage(imgs[i], monster1.x, monster1.y);
}
}
}
var main = function() {
draw();
requestAnimationFrame(main);
};
monsterXY1();
but this code gives me all the images at the same x and y so how i make each of them at random x and y ??

Use an image preloader to be sure all your images have loaded before you try to drawImage them:
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var cw=canvas.width;
var ch=canvas.height;
var imageURLs=[];
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house32x32transparent.png");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house32x32transparent.png");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house32x32transparent.png");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house32x32transparent.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[]
for(var i=0;i<imgs.length;i++){
var randomX=Math.min(cw-imgs[i].width,Math.random()*cw);
var randomY=Math.min(ch-imgs[i].height,Math.random()*ch);
ctx.drawImage(imgs[i],randomX,randomY);
}
}
body{ background-color: ivory; padding:10px; }
#canvas{border:1px solid red;}
<canvas id="canvas" width=300 height=300></canvas>

Try:
var imgs = [];
var fruits = ["fruit1.png", "fruit2.png", "fruit3.png", "fruit4.png"];
var monsterReady1 = false;
for (var i = 0; i < fruits.length; i++) {
imgs[i] = new Image();
imgs[i].onload = function() {
monsterReady1 = true;
};
imgs[i].src = fruits[i];
}
var draw = function() {
if (monsterReady1) {
for (var i = 0; i < fruits.length; i++) {
monster1.x = (Math.random() * (canvas.width - 100));
monster1.y = (Math.random() * (canvas.height - 100));
ctx.drawImage(imgs[i], monster1.x, monster1.y);
}
}
}
var main = function() {
draw();
requestAnimationFrame(main);
}
main();
I moved the monster.x and monster.y inside the loop.

Related

Suggestions to create lines in javascript

I am new to JavaScript, and trying to create a function that will draw lines on the canvas. This is currently what I have and it's not working. I may be doing unnecessary things and I need some suggestions for this code.
function start(){
var COUNT = 5;
for(var i = 0; i < COUNT; i++){
var row = 0;
var rect = new Rectangle(100, 100);
rect.setPosition(0, row);
rect.setColor(Color.blue);
var rect1 = new Rectangle(100, 100);
rect1.setPosition(100, row);
rect1.setColor(Color.red);
var rect2 = new Rectangle(100, 100);
rect2.setPosition(200, row);
rect2.setColor(Color.blue);
var rect3 = new Rectangle(100, 100);
rect3.setPosition(300, row);
rect3.setColor(Color.red);
add(rect);
add(rect1);
add(rect2);
add(rect3);
row + 100;
}
}
Are you trying to do something like this :
var ctx = canvas.getContext('2d')
var colors = ['red','blue']
function start(){
var COUNT = 5;
for(var i = 0; i < COUNT; i++)
for(var j = 0 ; j<4;j++){
var rect = [10,10];
ctx.fillStyle = colors[(i+j)%2];
ctx.fillRect(j*10, i*10, rect[0],rect[1]);
}
}
start();
https://jsfiddle.net/dbo3htov/29/

How to load any number of images onto canvas

How do i load any number of images onto the canvas. The number can be 5,6... how can i do that.So far i am only able to load 2 images but this code will not work for dynamic number of images.The code should be such that it should load many images.
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<canvas id="myCanvas" width="578" height="200"></canvas>
<script>
function loadImages(sources, callback) {
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('myCanvas');
var context = canvas.getContext('2d');
//var availableTags = <?php echo json_encode($img_arr1) ?>;
var sources = {
darthVader: 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg',
yoda: 'http://www.html5canvastutorials.com/demos/assets/yoda.jpg'
};
loadImages(sources, function(images) {
context.drawImage(images.darthVader, 100, 30, 200, 137);
context.drawImage(images.yoda, 350, 55, 93, 104);
});
</script>
</body>
</html>
Save relevant data as list of objects and loop through them:
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
//var availableTags = <?php echo json_encode($img_arr1) ?>;
var sourceSets = [];
var sources = {};
//Draw function
function draw() {
//Clear board
context.clearRect(-10, -10, 4000, 4000);
//Loop through images and draw each one
for (var i = 0; i < sourceSets.length; i++) {
context.drawImage(sourceSets[i].img, sourceSets[i].x, sourceSets[i].y, sourceSets[i].w, sourceSets[i].h);
}
}
function loadSource(src, x, y, w, h) {
//Setting defaults
if (src === void 0) {
src = '';
}
if (x === void 0) {
x = 0;
}
if (y === void 0) {
y = 0;
}
if (w === void 0) {
w = 100;
}
if (h === void 0) {
h = 100;
}
//Creating image and loading from src
if(sources[src] === void 0) {
sources[src] = new Image();
sources[src].onload = function () {
draw();
};
sources[src].src = src;
}
var img = sources[src];
img.src = src;
//Save all relevant data in an object
sourceSets.push({
src : src,
x : x,
y : y,
w : w,
h : h,
img : img
});
}
//Add whatever amount of images here
var amount = parseInt(prompt("amount",4));
for(var i = 0; i < amount; i++) {
if(i%2 === 0) {
loadSource('http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg', Math.random() * 400, Math.random() * 400, 200, 137);
} else {
loadSource('http://www.html5canvastutorials.com/demos/assets/yoda.jpg', Math.random() * 400, Math.random() * 400, 93, 104);
}
}
<canvas id="myCanvas" width="600" height="540"></canvas>

Compare multiple part of an image through canvas using resemble.js

I am trying to compare different blocks of an image(filled.png) with a specific block of another image(blank.png).
So far I have tried this :-
var canvas = document.createElement('canvas');
var context = canvas.getContext('2d');
canvas.width = 20;
canvas.height = 20;
var img = new Image();
img.onload = function(){
context.drawImage(img,53,61,20,20,0,0,20,20);
};
img.src ='blank.png';
var imgResult = new Image();
var image1,image2;
var canvasResult = document.createElement('canvas');
canvasResult.width = 20;
canvasResult.height = 20;
var contextResult = canvasResult.getContext('2d');
function compare(){
image1=new Image();
image1.onload= function(){
imgResult.onload = function(){
var x = 53;
for (var i = 1; i <= 20; i++) {
contextResult.clearRect(0, 0, 20, 20);
contextResult.drawImage(imgResult,x,61,20,20,0,0,20,20);
x += 23;
image2 = new Image();
image2.onload = function(){
resemble(image1.src).compareTo(image2.src).onComplete(function(data){
$('p').append('Diffrence : ' + data.misMatchPercentage+ '%</br>');
});
};
image2.src = canvasResult.toDataURL();
}
};
imgResult.src = 'filled.png';
}
image1.src=canvas.toDataURL();
}
But it is not working, getting same result on each iteration of for loop. So please help me find, where I am going wrong.
.onComplete - sounds asynchronous, and image2.onload DEFINITELY IS - but in the meantime you're changing contextResult ... asynchronous code strikes again
If you create a function which recursively calls itself when each iteration completes, you should have better results:
e.g. with minimal code changes to what you have:
imgResult.onload = function(){
var x = 53, i = 1;
var compare = function() {
contextResult.clearRect(0, 0, 20, 20);
contextResult.drawImage(imgResult,x,61,20,20,0,0,20,20);
x += 23;
image2 = new Image();
image2.onload = function(){
resemble(image1.src).compareTo(image2.src).onComplete(function (data) {
$('p').append('Diffrence : ' + data.misMatchPercentage+ '%</br>');
i += 1;
if (i <= 20) {
compare();
}
});
};
image2.src = canvasResult.toDataURL();
};
compare();
}

When dynamically creating images, why is the image array empty?

What I am trying to do is load images dynamically and then draw them on the screen. However, when I call console.log(images), it is empty.
Here is the code:
if (canvas.getContext)
{
var ctx = canvas.getContext("2d");
var images = new Array();
for (i = 0; i < mattes_array.length; i++)
{
var imgsrc = mattes_array[i]["imgsrc"];
var total_size = mattes_array[i]["total_size"];
var cpu = mattes_array[i]["cpu"];
var cid = mattes_array[i]["cid"];
var imageObj = new Image();
imageObj.onload = function() {
images[i] = imageObj;
console.log(images[i]);
};
imageObj.id = "matte_" + cid;
imageObj.src = imgsrc;
}
console.log(images); //this is empty
for (i = 0; i < mattes_array.length; i++)
{
var imgsrc = mattes_array[i]["imgsrc"];
var total_size = mattes_array[i]["total_size"];
var cpu = mattes_array[i]["cpu"];
var cid = mattes_array[i]["cid"];
var pattern = ctx.createPattern(images[i], 'repeat');
ctx.strokeStyle = pattern;
ctx.lineWidth = width - opening_width - (total_size * 2);
ctx.strokeRect(0, 0, width, height);
}
}
I have also tried doing it in one loop, but it seems to only draw the last image:
if (canvas.getContext)
{
var ctx = canvas.getContext("2d");
var images = new Array();
for (i = 0; i < mattes_array.length; i++)
{
var imgsrc = mattes_array[i]["imgsrc"];
var total_size = mattes_array[i]["total_size"];
var cpu = mattes_array[i]["cpu"];
var cid = mattes_array[i]["cid"];
var imageObj = new Image();
imageObj.onload = function() {
var pattern = ctx.createPattern(imageObj, 'repeat');
ctx.strokeStyle = pattern;
ctx.lineWidth = width - opening_width - (total_size * 2);
ctx.strokeRect(0, 0, width, height);
};
imageObj.id = "matte_" + cid;
imageObj.src = imgsrc;
}
}
Here is an image of what I am trying to do:
Images load asynchronously. You're trying to draw them before they are loaded. Give this a try:
if (canvas.getContext)
{
var ctx = canvas.getContext("2d");
var images = new Array();
var loaded = 0;
for (i = 0; i < mattes_array.length; i++)
{
var imgsrc = mattes_array[i]["imgsrc"];
var total_size = mattes_array[i]["total_size"];
var cpu = mattes_array[i]["cpu"];
var cid = mattes_array[i]["cid"];
var imageObj = new Image();
imageObj.onload = function() {
images[i] = imageObj;
console.log(images[i]);
if ( ++loaded === mattes_array.length ) onloaded();
};
imageObj.id = "matte_" + cid;
imageObj.src = imgsrc;
}
function onloaded() {
console.log(images); //this is won't be empty anymore
for (i = 0; i < mattes_array.length; i++)
{
var imgsrc = mattes_array[i]["imgsrc"];
var total_size = mattes_array[i]["total_size"];
var cpu = mattes_array[i]["cpu"];
var cid = mattes_array[i]["cid"];
var pattern = ctx.createPattern(images[i], 'repeat');
ctx.strokeStyle = pattern;
ctx.lineWidth = width - opening_width - (total_size * 2);
ctx.strokeRect(0, 0, width, height);
}
}
}

Scope issue with Coffeescript

I have some strange scope issue in Coffeescript.
I can't access to _this from the function #qr.callback, the _this doesn't seem to pass well. I never change this.imgName so the only reason that It doesn't work could be that _this is'nt passed well.
decode:(#callback) ->
_this= this
console.log 'before',_this.imgName
#qr= new QrCode()
#qr.callback= () ->
console.log "after:", _this.imgName
#qr.decode("data:image/png;base64,#{#base64Data}")
Edit:
I have tried using
console.log 'before',#imgName
#qr= new QrCode()
#qr.callback= () =>
console.log "after:", #imgName
#qr.decode("data:image/png;base64,#{#base64Data}")
But the output is the same
Edit2: QrCode code: This code comes from https://github.com/LazarSoft/jsqrcode. Howewer, as the source code of LazarSoft https://github.com/LazarSoft/jsqrcode/blob/master/src/qrcode.js did'nt contain a QrCode object that you could instantiate many times , I transformed the code to create many different instances of QrCode by creating a QrCode function instead of a global object qrcode.
QrCode= function ()
{
this.imagedata = null;
this.width = 0;
this.height = 0;
this.qrCodeSymbol = null;
this.debug = false;
this.sizeOfDataLengthInfo = [ [ 10, 9, 8, 8 ], [ 12, 11, 16, 10 ], [ 14, 13, 16, 12 ] ];
this.callback = null;
this.decode = function(src){
if(arguments.length==0)
{
var canvas_qr = document.getElementById("qr-canvas");
var context = canvas_qr.getContext('2d');
this.width = canvas_qr.width;
this.height = canvas_qr.height;
this.imagedata = context.getImageData(0, 0, this.width, this.height);
this.result = this.process(context);
if(this.callback!=null)
this.callback(this.result);
return this.result;
}
else
{
var image = new Image();
_this=this
image.onload=function(){
//var canvas_qr = document.getElementById("qr-canvas");
var canvas_qr = document.createElement('canvas');
var context = canvas_qr.getContext('2d');
var canvas_out = document.getElementById("out-canvas");
if(canvas_out!=null)
{
var outctx = canvas_out.getContext('2d');
outctx.clearRect(0, 0, 320, 240);
outctx.drawImage(image, 0, 0, 320, 240);
}
canvas_qr.width = image.width;
canvas_qr.height = image.height;
context.drawImage(image, 0, 0);
_this.width = image.width;
_this.height = image.height;
try{
_this.imagedata = context.getImageData(0, 0, image.width, image.height);
}catch(e){
_this.result = "Cross domain image reading not supported in your browser! Save it to your computer then drag and drop the file!";
if(_this.callback!=null)
_this.callback(_this.result);
return;
}
try
{
_this.result = _this.process(context);
}
catch(e)
{
// console.log('error:'+e);
_this.result = "error decoding QR Code";
}
if(_this.callback!=null)
_this.callback(_this.result);
}
image.src = src;
}
}
this.decode_utf8 = function ( s )
{
return decodeURIComponent( escape( s ) );
}
this.process = function(ctx){
var start = new Date().getTime();
var image = this.grayScaleToBitmap(this.grayscale());
//var image = this.binarize(128);
if(this.debug)
{
for (var y = 0; y < this.height; y++)
{
for (var x = 0; x < this.width; x++)
{
var point = (x * 4) + (y * this.width * 4);
this.imagedata.data[point] = image[x+y*this.width]?0:0;
this.imagedata.data[point+1] = image[x+y*this.width]?0:0;
this.imagedata.data[point+2] = image[x+y*this.width]?255:0;
}
}
ctx.putImageData(this.imagedata, 0, 0);
}
//var finderPatternInfo = new FinderPatternFinder().findFinderPattern(image);
var detector = new Detector(image,this);
var qRCodeMatrix = detector.detect();
/*for (var y = 0; y < qRCodeMatrix.bits.Height; y++)
{
for (var x = 0; x < qRCodeMatrix.bits.Width; x++)
{
var point = (x * 4*2) + (y*2 * this.width * 4);
this.imagedata.data[point] = qRCodeMatrix.bits.get_Renamed(x,y)?0:0;
this.imagedata.data[point+1] = qRCodeMatrix.bits.get_Renamed(x,y)?0:0;
this.imagedata.data[point+2] = qRCodeMatrix.bits.get_Renamed(x,y)?255:0;
}
}*/
if(this.debug)
ctx.putImageData(this.imagedata, 0, 0);
var reader = Decoder.decode(qRCodeMatrix.bits,this);
var data = reader.DataByte;
var str="";
for(var i=0;i<data.length;i++)
{
for(var j=0;j<data[i].length;j++)
str+=String.fromCharCode(data[i][j]);
}
var end = new Date().getTime();
var time = end - start;
console.log(time);
return this.decode_utf8(str);
//alert("Time:" + time + " Code: "+str);
}
this.getPixel = function(x,y){
if (this.width < x) {
throw "point error";
}
if (this.height < y) {
throw "point error";
}
point = (x * 4) + (y * this.width * 4);
p = (this.imagedata.data[point]*33 + this.imagedata.data[point + 1]*34 + this.imagedata.data[point + 2]*33)/100;
return p;
}
this.binarize = function(th){
var ret = new Array(this.width*this.height);
for (var y = 0; y < this.height; y++)
{
for (var x = 0; x < this.width; x++)
{
var gray = this.getPixel(x, y);
ret[x+y*this.width] = gray<=th?true:false;
}
}
return ret;
}
this.getMiddleBrightnessPerArea=function(image)
{
var numSqrtArea = 4;
//obtain middle brightness((min + max) / 2) per area
var areaWidth = Math.floor(this.width / numSqrtArea);
var areaHeight = Math.floor(this.height / numSqrtArea);
var minmax = new Array(numSqrtArea);
for (var i = 0; i < numSqrtArea; i++)
{
minmax[i] = new Array(numSqrtArea);
for (var i2 = 0; i2 < numSqrtArea; i2++)
{
minmax[i][i2] = new Array(0,0);
}
}
for (var ay = 0; ay < numSqrtArea; ay++)
{
for (var ax = 0; ax < numSqrtArea; ax++)
{
minmax[ax][ay][0] = 0xFF;
for (var dy = 0; dy < areaHeight; dy++)
{
for (var dx = 0; dx < areaWidth; dx++)
{
var target = image[areaWidth * ax + dx+(areaHeight * ay + dy)*this.width];
if (target < minmax[ax][ay][0])
minmax[ax][ay][0] = target;
if (target > minmax[ax][ay][1])
minmax[ax][ay][1] = target;
}
}
//minmax[ax][ay][0] = (minmax[ax][ay][0] + minmax[ax][ay][1]) / 2;
}
}
var middle = new Array(numSqrtArea);
for (var i3 = 0; i3 < numSqrtArea; i3++)
{
middle[i3] = new Array(numSqrtArea);
}
for (var ay = 0; ay < numSqrtArea; ay++)
{
for (var ax = 0; ax < numSqrtArea; ax++)
{
middle[ax][ay] = Math.floor((minmax[ax][ay][0] + minmax[ax][ay][1]) / 2);
//Console.out.print(middle[ax][ay] + ",");
}
//Console.out.println("");
}
//Console.out.println("");
return middle;
}
this.grayScaleToBitmap=function(grayScale)
{
var middle = this.getMiddleBrightnessPerArea(grayScale);
var sqrtNumArea = middle.length;
var areaWidth = Math.floor(this.width / sqrtNumArea);
var areaHeight = Math.floor(this.height / sqrtNumArea);
var bitmap = new Array(this.height*this.width);
for (var ay = 0; ay < sqrtNumArea; ay++)
{
for (var ax = 0; ax < sqrtNumArea; ax++)
{
for (var dy = 0; dy < areaHeight; dy++)
{
for (var dx = 0; dx < areaWidth; dx++)
{
bitmap[areaWidth * ax + dx+ (areaHeight * ay + dy)*this.width] = (grayScale[areaWidth * ax + dx+ (areaHeight * ay + dy)*this.width] < middle[ax][ay])?true:false;
}
}
}
}
return bitmap;
}
this.grayscale = function(){
var ret = new Array(this.width*this.height);
for (var y = 0; y < this.height; y++)
{
for (var x = 0; x < this.width; x++)
{
var gray = this.getPixel(x, y);
ret[x+y*this.width] = gray;
}
}
return ret;
}
}
var image = new Image();
_this=this
May lightning strike you, you're coding CoffeeScript too much! You forgot a var declaration here, so the ninth invocation of decode overwrites the global _this with its this instance - and when each decoding is finished, they all call the same callback.
Fix it by using
var _this = this;
or
var image = new Image,
_this = this;
or by using CoffeeScript everywhere :-)

Categories