Array of images in canvas not working - javascript

Could someone please help to make the below code work. also is there any other way to display the images without using onload?
<head id="Head1" runat="server">
<meta name="viewport" content="width=device-width,initial-scale=1.0">
<title></title>
<script src="//code.jquery.com/jquery-1.11.0.min.js"></script>
<script type="text/javascript">
$(document).ready(function () {
var c = document.getElementById("myCanvas");
c.width = $(document).width();
c.height = $(document).height();
var ctx = c.getContext("2d");
var imgArray = new Array();
imgArray[0] = new Image();
imgArray[1] = new Image();
imgArray[0].src = "1.png";
imgArray[1].src = "2.png";
var x = 30;
var y = 40;
for (var i = 0; i < 2; i++) {
imgArray[i].onload = function () {
ctx.drawImage(imgArray[i], x, y);
}
x = x + 20;
}
});
</script>
</head>
I want images to be displayed on canvas using array. it works fine if i use array without for loop. please help in fixing the issue.
<body style="margin:0; height:100%; width:100%; overflow:hidden;" >
<canvas id="myCanvas" style="display:block; " >
Your browser does not support the HTML5 canvas tag.
</canvas>
</body>
</html>

It's bad practice to define a function within a loop. Try defining it outside of the loop with a named function. Also it'd probably be better to set the src of the img after the onload function is attached. Something like:
$(document).ready(function () {
var c = document.getElementById("myCanvas");
c.width = $(document).width();
c.height = $(document).height();
var ctx = c.getContext("2d");
var imgArray = new Array();
imgArray[0] = new Image();
imgArray[1] = new Image();
var x = 30;
var y = 40;
function onImageLoad() {
ctx.drawImage(this, x, y);
x = x + 20;
}
for (var i = 0; i < 2; i++) {
imgArray[i].onload = onImageLoad;
}
imgArray[0].src = "1.png";
imgArray[1].src = "2.png";
});
If you must have the loop in the function (which you don't), you would need to wrap it within a closure so that each image gets it's own onload function instead of defining the same function which is what happens in your case.
Something similar to the following would probably work:
for (var i = 0; i < 2; i++) {
imgArray[i].onload = (function(idx) {
return function() {
ctx.drawImage(imgArray[idx], x, y);
x = x + 20;
}
})(i)
}

This is how you could do it:
<script type="text/javascript" src="http://code.jquery.com/jquery-1.11.1.min.js"></script>
<script type="text/javascript">
$(document).ready(function()
{
// Source
var imgArray = new Array();
imgArray[0] = new Image();
imgArray[1] = new Image();
imgArray[0].src = "http://png-2.findicons.com/files/icons/963/very_emotional_emoticons/64/64_18.png";
imgArray[1].src = "http://png-3.findicons.com/files/icons/963/very_emotional_emoticons/64/64_30.png";
// Draw Images
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var startX = 0;
for (var i = 0; i < imgArray.length; i++) {
ctx.drawImage(imgArray[i], startX, 0);
startX += 74;
}
});
</script>
<canvas id="myCanvas" style="display:block;">
Your browser does not support the HTML5 canvas tag.
</canvas>
Outputs:
P.S. The images are 64x64 (width x height). So to draw them next to each other with 10px spacing, I add 10 to 64 (width), hence I do startX += 74; and the images draw like that.
You should be able to modify this code to meet your own needs.

Related

Fitting Multiple Images on a web page that update from an API

I am Trying to Build a simple web page to display a feed from my cameras that pulls a still image from the camera via the cameras api and then regrabs the image with the API (so i can configure the frame rate of the cameras to cut down on mobile data)
I have managed to build a simple website with just one of the displays, but i want to be able to display all 8 of my cameras, IP addresses 192.168.0.157 - 165
My current code is
<html>
<head>
<script type="text/JavaScript">
var refreshInterval = 1000;
var url1 = "http://192.168.0.157/api/still?passwd=pass&"
var drawDate = true;
var img1;
function init() {
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
img = new Image();
img.onload = function() {
canvas.setAttribute("width", img.width)
canvas.setAttribute("height", img.height)
context.drawImage(this, 0, 0);
if(drawDate) {
var now = new Date();
var text = now.toLocaleDateString() + " " + now.toLocaleTimeString();
var maxWidth = 100;
var x = img.width-10-maxWidth;
var y = img.height-10;
context.strokeStyle = 'black';
context.lineWidth = 2;
context.strokeText(text, x, y, maxWidth);
context.fillStyle = 'white';
context.fillText(text, x, y, maxWidth);
}
};
refresh();
}
function refresh()
{
img.src = img.src = url1 + "t=" + new Date().getTime();
setTimeout("refresh()",refreshInterval);
}
</script>
<title>Test4</title>
</head>
<body onload="JavaScript:init();">
<canvas id="canvas"/>
</body>
</html>
Thanks in advance
I'm thinking make an array for every camera IP, and do all the API stuff for each of those.
var ip = [
"192.168.0.157",
"192.168.0.158",
"192.168.0.159",
"192.168.0.160",
"192.168.0.161",
"192.168.0.162",
"192.168.0.163",
"192.168.0.164",
"192.168.0.165"
];
var img = [];
function init() {
var canvas = document.getElementById("canvas");
var context = canvas.getContext("2d");
for (var i = 0; i < ip.length; i++) {
img[i] = new Image();
img[i].onload = (function() {
canvas.setAttribute("width", img[i].width);
canvas.setAttribute("height", img[i].height);
context.drawImage(this, 0, 0);
if (drawDate) {
var now = new Date();
var text = now.toLocaleDateString() + " " + now.toLocaleTimeString();
var maxWidth = 100;
var x = img[i].width - 10 - maxWidth;
var y = img[i].height - 10;
context.strokeStyle = 'black';
context.lineWidth = 2;
context.strokeText(text, x, y, maxWidth);
context.fillStyle = 'white';
context.fillText(text, x, y, maxWidth);
}
})();
}
refresh();
};
function refresh() {
for (var i = 0; i < img.length; i++) {
img[i].src = "http://" + ip[i] + "/api/still?passwd=pass&t=" + new Date().getTime();
}
setTimeout("refresh()",refreshInterval);
}

Drawing image on canvas in loop not working

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

HTML Canvas Images - Drawing multi canvas image in a page

i have a problem with canvas.
i can draw a canvas with single image, but i can't draw each canvas with image separate.
- if data just have one image it's working fine, but data have multiple image it's not working
can you help me ?
<script>
var h_notepad = 500;
var w_notepad = 737;
var data = [
{dataImageURL: "1_sat_1.png"},
{dataImageURL: "1_sat_2.png"},
{dataImageURL: "1_sat_3.png"},
{dataImageURL: "1_sat_4.png"}
];
for(var i = 0; i < data.length ; i++){
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
var img = new Image();
canvas.width = w_notepad;
canvas.height = h_notepad;
img.crossOrigin = 'anonymous';
img.width = w_notepad;
img.height = h_notepad;
console.log(img);
img.onload = function(){
ctx.drawImage(img, 0, 0, w_notepad, h_notepad);
};
img.src = data[i].dataImageURL;
$('body').append(canvas);
}
</script>
<html>
<head>
<meta charset="utf-8">
<title>DRAWING</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<meta charset="utf-8">
</head>
<body>
</body>
</html>
I guess you only get the last one.
It's a closure problem.
When the load event fires, img and ctx only refer to the last ones created.
So you draw data.length time on the same canvas.
To avoid it, you can use this and wrap the canvas creation in the onload handler:
var imgs = ['http://lorempixel.com/200/300/', 'http://lorempixel.com/500/300/', 'http://lorempixel.com/200/100/'];
for (var i = 0; i < imgs.length; i++) {
var img = new Image();
var width = 500;
var height = 300;
img.onload = function() {
var c = document.createElement('canvas');
c.width = width;
c.height = height;
document.body.appendChild(c);
var ctx = c.getContext('2d');
ctx.drawImage(this, 0,0, width, height);
};
img.src = imgs[i];
}
Problem is that onload is asynchronous. So all your code runs before any of onload functions will be called. That is why your function
img.onload = function(){
ctx.drawImage(img, 0, 0, w_notepad, h_notepad);
};
uses the latest ctx and renders all images in this context.
What you can do is cover this asynchronous call with a synchronous function scope:
(function(ctx, img, w_notepad, h_notepad) {
img.onload = function(){
ctx.drawImage(img, 0, 0, w_notepad, h_notepad);
};
})(ctx, img, w_notepad, h_notepad);
This isolates the variables and keeps there values until you receive the image.

Modify pixels in remote image in plain html/js

I am new to Javascript, I would like to modify the brightness of any remote image given in an input form.
I have tried to use Canvas but I got this issue.
I want the following code to work directly via "file:///test.html". How can I simply achieve that ?
<html>
<head>
<script type="text/javascript">
function readImg() {
img = new Image();
url = document.getElementById('url').value;
document.getElementById('showImg').innerHTML='<img src="'+ url +'" />';
img.src = url;
canvas = document.createElement("canvas");
canvas.width = img.width;
canvas.height = img.height;
ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
img.crossOrigin = "Anonymous";
imgData = ctx.getImageData(0,0,canvas.width,canvas.height); // not working !!
brightness(imgData);
}
function brightness(imgData) {
var dataimg = imgData.data;
for (var i = 0; i < dataimg.size; i += 4 ) {
dataimg[i] += 10;
dataimg[i+1] += 10;
dataimg[i+2] += 10;
}
}
</script>
</head>
<body>
<input id="url" type="text" onChange="readImg()"></input>
<div id='showImg'></div>
</body>
</html>
You have to give Chrome explicit access to local files from local html files.
You have to run Chrome with --allow-file-access-from-files flag.
"C:\PathTo\Chrome.exe" --allow-file-access-from-files
You can find more info about it here as it was already discussed:
https://stackoverflow.com/a/18587027/4103991
#EDIT://
Execute commands related to img element inside img.onload event handler.
Your code should look somewhat like that:
<html>
<head>
<script type="text/javascript">
function readImg() {
img = new Image();
url = document.getElementById('url').value;
document.getElementById('showImg').innerHTML='<img src="'+ url +'" />';
canvas = document.createElement("canvas");
img.onload = function(){
canvas.width = img.width;
canvas.height = img.height;
ctx = canvas.getContext("2d");
ctx.drawImage(img, 0, 0);
imgData = ctx.getImageData(0,0,canvas.width,canvas.height);
brightness(imgData);
}
img.src = url;
img.crossOrigin = "Anonymous";
}
function brightness(imgData) {
var dataimg = imgData.data;
for (var i = 0; i < dataimg.size; i += 4 ) {
dataimg[i] += 10;
dataimg[i+1] += 10;
dataimg[i+2] += 10;
}
}
</script>
</head>
<body>
<input id="url" type="text" onChange="readImg()"></input>
<div id='showImg'></div>
</body>
</html>

Why does the image not display?

Why does the image not display to the canvas in this example?
Code:
<!DOCTYPE html>
<html>
<head>
<title></title>
<script>
/*
var lockOrientation = screen.lockOrientation || screen.mozLockOrientation || screen.msLockOrientation;
screen.lockOrientation('landscape');
if (lockOrientation("landscape-primary")) {
screen.lockOrientation('landscape');
}
*/
var canvas = document.getElementById('myCanvas');
var context = canvas.getContext('2d');
var x = 10;
var y = 10;
var width = 470;
var height = 310;
var imageObj = new Image();
imageObj.onload = function() {
context.drawImage(imageObj, x, y, width, height);
};
imageObj.src = 'http://www.html5canvastutorials.com/demos/assets/darth-vader.jpg';
</script>
</head>
<body>
<canvas id="myCanvas" width="470" height="310" style="border:5px solid #123456;"></canvas>
</body>
</html>
You need to wait for the document to load before trying to select elements in the page.
Try wrapping your code like this:
window.onload = function() {
// your code goes here
};

Categories

Resources