Display image in canvas with Javascript? - javascript

I want to be able to click on a button on my page and load an image into a canvas at some X,Y coordinates?
The following code is what I have below. I would like the image to be in either image/photo.jpg or in the same directory but preferably in a subdirectory of the main page.
**Question: How to make a JPG show up in a canvas with the click of a button on the web page?
Code:
<!DOCTYPE html>
<html>
<script>
function draw(){
var ctx = document.getElementById("myCanvas").getContext("2d");
var img = new Image():
// img.src = "2c.jpg";
img.src = "/images/2c.jpg";
ctx.drawImage(img,0,0);
}
</script>
<body background="Black">
<div align="center">
<button type="button" onclick="draw()">Show Image on Canvas</button>
<canvas id="myCanvas" width="900" height="400" style="border:2px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.
</canvas>
</div>
<script>
var c=document.getElementById("myCanvas");
var ctx=c.getContext("2d");
ctx.font="20px Arial";
ctx.fillText("Royal Flush $",500,50);
ctx.fillText("Striaght Flush $",500,80);
ctx.fillText("Flush $",500,110);
ctx.fillText("Four of a Kind $",500,140);
ctx.fillText("Full House $",500,170);
ctx.fillText("Three of a Kind $",500,200);
ctx.fillText("Two Pair $",500,230);
ctx.fillText("Pair of ACES $",500,260);
ctx.rect(495,10,270,350);
ctx.stroke();
</script>
</body>
</html>
March 6th, 2014 Code:
How is the following code not working. Do you have to have an ID tag on Canvas. The page will display but for some reason the image will not when the button is clicked. The image is in the same directory that my index.html file is in.
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<style type="text/css">
canvas{
border: 5px solid black;
}
</style>
</html>
<button id="galaxy">Add image #1</button>
<button id="circles">Add image #2</button><span></span>
<canvas width="500" height="500"></canvas>
<script>
var Images = {};
function loadImages(list){
var total = 0;
document.querySelector("span").innerText = "...Loading...";
for(var i = 0; i < list.length; i++){
var img = new Image();
Images[list[i].name] = img;
img.onload = function(){
total++;
if(total == list.length){
document.querySelector("span").innerText = "...Loaded.";
}
};
img.src = list[i].url;
}
}
function drawImage(img){
var ctx = document.querySelector("canvas").getContext("2d");
ctx.drawImage(Images[img], 0, 0, 50, 50);
}
loadImages([{
name: "2c.jpg",
url: "mp.jpg"
},{
name: "mp.jpg",
url: "mp.jpg"
}]);
document.querySelector("#galaxy").addEventListener("click", function(){
drawImage("galaxy");
});
document.querySelector("#circles").addEventListener("click", function(){
drawImage("weirdCircles");
});
</script>
</html>

Wait till the image is loaded before drawing:
var img = new Image();
img.onload = function(){ /*or*/ img.addEventListener("load", function(){
ctx.drawImage(img,0,0); ctx.drawImage(img,0,0);
}; };
img.src = "/images/2c.jpg";
Demo: http://jsfiddle.net/DerekL/YcLgw/
If you have more than one image in your game,
It is better to preload all images before it starts.
Preload images: http://jsfiddle.net/DerekL/uCQAH/ (Without jQuery: http://jsfiddle.net/DerekL/Lr9Gb/)
If you are more familiar with OOP: http://jsfiddle.net/DerekL/2F2gu/
function ImageCollection(list, callback){
var total = 0, images = {}; //private :)
for(var i = 0; i < list.length; i++){
var img = new Image();
images[list[i].name] = img;
img.onload = function(){
total++;
if(total == list.length){
callback && callback();
}
};
img.src = list[i].url;
}
this.get = function(name){
return images[name] || (function(){throw "Not exist"})();
};
}
//Create an ImageCollection to load and store my images
var images = new ImageCollection([{
name: "MyImage", url: "//example.com/example.jpg"
}]);
//To pick and draw an image from the collection:
var ctx = document.querySelector("canvas").getContext("2d");
ctx.drawImage(images.get("MyImage"), 0, 0);

Related

How to draw images on an html canvas in a loop

I am trying to draw images on a canvas in a loop
In the following code, if I click on Next the 5 images appear one after the other. If I click on All only the last image appears
What is wrong?
<html>
<head>
<style>
.display-grid{
display: grid;
grid-template-columns: auto auto auto auto;
padding: 10px;
}
</style>
</head>
<body>
<div id="my-grid">
<div class="display-grid">
<span><canvas class="canvas" id="display-0"></canvas></span>
<span><canvas class="canvas" id="display-1"></canvas></span>
<span><canvas class="canvas" id="display-2"></canvas></span>
<span><canvas class="canvas" id="display-3"></canvas></span>
<span><canvas class="canvas" id="display-4"></canvas></span>
</div>
</div>
<button id="next-image">Next</button>
<button id="all-images">All</button>
<script type="text/javascript">
last_image = -1
var next_button= document.getElementById('next-image');
var all_button= document.getElementById('all-images');
next_button.onclick = function(){nextImage()};
all_button.onclick = function(){allImages()};
function nextImage() {
last_image ++
var canvas = document.getElementById('display-'+last_image.toString());
var context = canvas.getContext('2d');
var imageObj = new Image();
imageObj.onload = function() {
context.drawImage(imageObj, 0, 0);
};
imageObj.src = 'image_'+last_image.toString()+'.png';
}
function allImages() {
for (index = 0; index < 5; index++) {
var canvas = document.getElementById('display-'+index.toString());
var context = canvas.getContext('2d');
var imageObj = new Image();
imageObj.onload = function() {
context.drawImage(imageObj, 0, 0);
};
imageObj.src = 'image_'+index.toString()+'.png';
}
}
</script>
</body>
</html>
It happens because the onload function isn't called in the same order as the loop. Some images may take longer to load than others.
You could fix it by checking the image name to know which image is loaded, and then you know in which canvas it should be drawn.
function allImages() {
for (let index = 0; index < 5; index++) {
let imageObj = new Image();
imageObj.name = "display-"+index
imageObj.onload = function() {
console.log("loaded : " + this.name)
let canvas = document.getElementById(this.name);
let context = canvas.getContext('2d');
context.drawImage(this, 0, 0);
};
imageObj.src = 'image_'+index+'.png';
}
}

How to add a dynamic id into a loader in canvas

I decided to load the images first then, draw it unto the canvas.
I want to add a button to allow the image to be moved around. For that I need the ID of the image. Does the image have an ID or can I give the image an id?
I want to be able to change the ID of the image with a loop. For example, everything in a certain area of the canvas becomes pit1marble1, pit1marble2.
<!DOCTYPE HTML>
<html>
<head>
<style>
body {
margin: 0px;
padding: 0px;
}
</style>
</head>
<body>
<div>
<canvas id="myCanvas" width="1024" height="479" usemap="Canvas"></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 sources = {
background: 'MANCALA-game_bg_combined3.png',
};
loadImages(sources, function(images) {
context.drawImage(images.background, 0, 0, 1024, 479);
});
</script>
</body>
</html>

Wrong base64 from canvas

Try a couple of days to solve one problem, but I can not understand why it is impossible. In canvas pictures drawn but the derivation gives wrong base64. I did not understand why. I just started, and didn't have great experience javascript. Help a newbie who can.
HTML:
<canvas id="canvas" width="400" height="300"></canvas>
<textarea id="base64" rows="10" cols="80"></textarea>
<img id="image">
JAVASCRIPT
function loadImages(sources, callback) { var images = {}; var loadedImages = 0; var numImages = 0; 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('canvas'); var context = canvas.getContext('2d'); var sources = { a: 'http://www.prairiedogmag.com/wp-content/uploads/2012/08/Cute-Animals-office-bat-4-200x300.jpg', b: 'http://worldnewspress.net/wp-content/uploads/2014/03/happiest-animals-all-time-18-200x300.jpg' }; loadImages(sources, function(images) { context.fillStyle = "red"; context.fillRect(0, 0, 400, 300); context.drawImage(images.a, 0, 0, 200, 300); context.drawImage(images.b, 201, 0, 200, 300); }); var url = document.getElementById('base64').value =document.getElementById('canvas').toDataURL(); document.getElementById('image').src = url;
To execute the context.toDataURL method any images drawn on the canvas must originate from the same domain as the web page code.
If not, you fail cross-domain security and the browser will refuse to do .toDataURL.
It looks like you are pulling cross-domain images and therefore failing this security concern.
Check out CORS security:
http://en.wikipedia.org/wiki/Cross-origin_resource_sharing
Here's example working code and a Demo: http://jsfiddle.net/m1erickson/76xF3/
This example fetches images from a server that's configured to deliver images in a cross-domain compliant way. There are multiple configuration adjustments that must be done on the server. Also notice the code: crossOrigin="anonymous". That's the code on the client side that allows cross-origin images (the server must be configured properly first).
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
var canvas=document.getElementById("canvas");
var context=canvas.getContext("2d");
var imageURLs=[]; // put the paths to your images here
var imagesOK=0;
var imgs=[];
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/multple/character1.png");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/multple/character3.png");
loadAllImages(start);
function loadAllImages(callback){
for (var i=0; i<imageURLs.length; i++) {
var img = new Image();
img.crossOrigin="anonymous";
imgs.push(img);
img.onload = function(){
imagesOK++;
if (imagesOK>=imageURLs.length ) {
callback();
}
};
img.onerror=function(){alert("image load failed");}
img.src = imageURLs[i];
}
}
function start(){
// the imgs[] array now holds fully loaded images
// the imgs[] are in the same order as imageURLs[]
context.fillStyle = "red";
context.fillRect(0,0,120,110);
context.drawImage(imgs[0], 0, 0, 60, 110);
context.drawImage(imgs[1], 60, 0, 60, 110);
var url = document.getElementById('base64').value =canvas.toDataURL();
document.getElementById('image').src = canvas.toDataURL();
}
}); // end $(function(){});
</script>
</head>
<body>
<h4>The canvas</h4>
<canvas id="canvas" width=120 height=110></canvas>
<h4>The image created from the canvas .toDataURL</h4>
<img id="image">
<h4>The base64 encoded image data</h4>
<textarea id="base64" rows="10" cols="80"></textarea>
</body>
</html>

How to identify which canvas was clicked

In the code below there are two canvases clicking on which will open the file browser to open an image. I want to display the opened image in that canvas which was clicked. but
1) the problem is once the control is inside the handleFile I don't know which one of the canvases was originally clicked! how can I do that or how can I pass the canvas as parameter to the function handleFile ?
2)what if I wanted to write something onto textarea1 when clicked on canvas1, write to textarea2 when clicked on canvas2?
<html>
<head>
</head>
<body>
<input type="file" id="fileLoader" name="fileLoader" style="display: none" />
<canvas id="bufferCanvas"></canvas>
<canvas id="canvas1" width="200" height="200" style="cursor:pointer; border:2px solid #000000"></canvas>
<canvas id="canvas2" width="200" height="200" style="cursor:pointer; border:2px solid #ff6a00"></canvas>
<textarea id="textarea1" rows="4" cols="50"></textarea>
<textarea id="textarea2" rows="4" cols="50"></textarea>
<script src="upload.js"></script>
</body>
</html>
and here is upload.js
var fileLoader = document.getElementById('fileLoader');
var bufferCanvas = document.getElementById('bufferCanvas');
var allCanvases = document.getElementsByTagName("Canvas");
for (var i = 1; i < allCanvases.length; ++i) {
allCanvases[i].getContext("2d").fillStyle = "blue";
allCanvases[i].getContext("2d").font = "bold 20px Arial";
allCanvases[i].getContext("2d").fillText("image " + i + " of 1", 22, 20);
allCanvases[i].onclick = function (e) {
fileLoader.click(e);
}
}
fileLoader.addEventListener('change', handleFile, false);
var textarea1 = document.getElementById('textarea1');
var ctx = bufferCanvas.getContext('2d');
function handleFile(e) {
// I wanna know what canvas was clicked
//So I can display the image on the canvas which was clicked
var reader = new FileReader();
reader.onload = function (event) {
var img = new Image();
img.onload = function () {
bufferCanvas.width = img.width;
bufferCanvas.height = img.height;
ctx.drawImage(img, 0, 0);
dataURL = bufferCanvas.toDataURL('image/png'); // here is the most important part because if you dont replace you will get a DOM 18 exception;
// window.location.href = dataURL;// opens it in current windows for testing
textarea1.innerHTML = dataURL;
}
img.src = event.target.result;
}
reader.readAsDataURL(e.target.files[0]);
}
The problem is the onclick for the canvas is firing a click for the fileloader which has it's own event. To do what you want you can create global var to hold the <canvas> that was clicked.
var fileLoader = document.getElementById('fileLoader');
var bufferCanvas = document.getElementById('bufferCanvas');
var allCanvases = document.getElementsByTagName("Canvas");
var clickedCanvas = ''; //<---- will hold the triggering canvas
Then in your onclick function you can set html element to clickedCanvas
for (var i = 1; i < allCanvases.length; ++i) {
...
...
...
allCanvases[i].onclick = function (e) {
clickedCanvas = e.srcElement; // <--- set the clicked on canvas
fileLoader.click(e);
}
}
Now in function handleFile(e) you should be able to get the canvas from clickedCanvas
Also I would clear out clickedCanvas after you are done so you aren't retaining the last event.
Fiddle

Fading a loaded image into Canvas with drawImage

This question about crossfading images already gave an answer to the crossfading solution in Canvas. I am trying to do the same thing, only difference is that i am trying to fade images that are loaded on runtime.
The images are loaded propperly but no fade is visible. Is this not working because of the loaded images? Thanks.
HTML
<div id="wrapper">
<canvas id="bg1"></canvas>
<canvas id="bg2"></canvas>
</div>
JS
var toggle = true;
var canvas = document.getElementById('bg1');
canvas.width = $(document).width();
canvas.height = $(document).height();
var ctx = canvas.getContext('2d');
var canvas2 = document.getElementById('bg2');
canvas2.width = $(document).width();
canvas2.height = $(document).height();
var ctx2 = canvas2.getContext('2d');
var image = new Image();
image.src = 'download1.jpg';
var image2 = new Image();
image2.src = 'download2.jpg';
image.onload = function() {
ctx.drawImage(image, 0, 0, 200, 100);
ctx2.drawImage(image2, 0, 0, 200, 100);
};
$('#wrapper').click(function () {
if (toggle)
{
$('#bg2').fadeIn();
$('#bg1').fadeOut();
}
else
{
$('#bg1').fadeIn();
$('#bg2').fadeOut();
}
toggle = !toggle;
});
Yep, you need to give your images time to load.
But also, jQuery cannot do fadeIn/fadeout on a canvas element so you will have to do that manually.
Demo: http://jsfiddle.net/m1erickson/zw9S4/
Code:
<!doctype html>
<html>
<head>
<link rel="stylesheet" type="text/css" media="all" href="css/reset.css" /> <!-- reset css -->
<script type="text/javascript" src="http://code.jquery.com/jquery.min.js"></script>
<style>
body{ background-color: ivory; }
canvas{border:1px solid red;}
</style>
<script>
$(function(){
$("#fade").hide();
var imageURLs=[]; // put the paths to your images here
var imagesOK=0;
var imgs=[];
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house204-1.jpg");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house204-2.jpg");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house204-3.jpg");
imageURLs.push("https://dl.dropboxusercontent.com/u/139992952/stackoverflow/house204-4.jpg");
loadAllImages();
//
function loadAllImages(){
for (var i=0; i<imageURLs.length; i++) {
var img = new Image();
imgs.push(img);
img.onload = function(){
imagesOK++;
if (imagesOK>=imageURLs.length ) {
$("#fade").show();
ctx.drawImage(imgs[0],0,0);
}
};
img.onerror=function(){alert("image load failed");}
img.crossOrigin="anonymous";
img.src = imageURLs[i];
}
}
var canvas=document.getElementById("canvas");
var ctx=canvas.getContext("2d");
var fadeOutIndex=imgs.length-1;
var fadeInIndex=0;
var fadePct=0;
function animateFade(){
if(fadePct>100){return;}
requestAnimationFrame(animateFade);
ctx.clearRect(0,0,canvas.width,canvas.height);
draw(imgs[fadeInIndex],fadePct/100);
draw(imgs[fadeOutIndex],(1-fadePct/100));
fadePct++;
}
function draw(img,opacity){
ctx.save();
ctx.globalAlpha=opacity;
ctx.drawImage(img,0,0);
ctx.restore();
}
$("#fade").click(function(){
fadePct=0;
if(++fadeOutIndex == imgs.length){fadeOutIndex=0;}
if(++fadeInIndex == imgs.length){fadeInIndex=0;}
animateFade();
});
}); // end $(function(){});
</script>
</head>
<body>
<button id="fade">Fade to next Image</button><br>
<canvas id="canvas" width=204 height=204></canvas><br>
</body>
</html>
Try to fade in/out the images directly on the canvas instead of fading in and out the canvas elements (or there is not really any point using the canvas as you could use image elements instead).
First, of course, wait for the images to load:
var isBusy = false, /// for fade loop
count = 2; /// number of images to load
image = new Image();
image2 = new Image();
/// setup load handler
image.onload = image2.onload = handleLoad;
image.src = 'download1.jpg';
image2.src = 'download2.jpg';
function handleLoad() {
count--;
if (count === 0) {
/// when loaded draw a single image onto canvas
ctx.drawImage(image, 0, 0, ctx.canvas.width, ctx.canvas.height);
}
};
Now we can change the click handler a little bit around and use canvas only to do the fade in of the next image:
$('#wrapper').click(function () {
var img, /// current image to fade in
opacity = 0; /// current globalAlpha of canvas
/// if we're in a fade exit until done
if (isBusy) return;
isBusy = true;
/// what image to use
img = toggle ? image2 : image;
/// fade in
(function fadeIn() {
/// set alpha
ctx.globalAlpha = opacity;
/// draw image with current alpha
ctx.drawImage(img, 0, 0, ctx.canvas.width, ctx.canvas.height);
/// increase alpha to 1, then exit resetting isBusy flag
opacity += 0.02;
if (opacity < 1)
requestAnimationFrame(fadeIn);
else
isBusy = false;
})();
toggle = !toggle;
});
Online demo
Hope this helps.

Categories