Stacking multiple canvases in HTML5 - javascript

I am trying to use four canvases stacked upon eachother but the contents of them won't display besides the contents of the one on the top. I put z-index values to them in order in which I'd like them to display but only the top one is displaying the contents. Their position is absolute and their z indexes are 1, 2, 3 and 4. Is there anything more to it that makes them not display? Or, how many canvases could I stack together in order for all of their contents to display?
I have this:
<div></div>
<canvas id="bg" width="500" height="500"></canvas> <!--z-index:1 -->
<canvas id="lc" width="500" height="500"></canvas> <!--z-index:2 -->
<canvas id="rc" width="500" height="500"></canvas> <!--z-index:3 -->
<canvas id="ch" width="500" height="500"></canvas> <!--z-index:4 -->
<!-- Script that draws image in each canvas with different x and y values -->
The problem is that when I run the function, the picture I am drawing only appears once, which means it only drew it on one canvas... For example, I'll have the script something like this:
function drawImgs() {
var bg = document.getElementById('bg').getContext('2d'),
lc = document.getElementById('lc').getContext('2d'),
rc = document.getElementById('rc').getContext('2d'),
ch = document.getElementById('ch').getContext('2d'),
img = new Image();
img.src = "image.png";
bg.drawImage(img,0,0);
lc.drawImage(img,64,64);
rc.drawImage(img,128,128);
ch.drawImage(img,192,192);
}
drawImgs();
It will only draw the image on the ch canvas, at X:192, Y:192. Why is that?
Is there a way to prevent it or at least make sure that all the images are drawn?
Is it because I'm using the same image or are the canvasses just not being transparent?
Is there a limit to how many canvasses you can look through?
Edit:
However, if I only have two canvasses, both images render. Why is this? Couldn't at least two images render if I have four canvasses stacked together?
Edit:
I was messing around with the code that I recieved from you guys (thanks for all the information, everything helped) and I tried to put it into my actual project (I tested the code and it was working before I put it into my project) but the once I put it into my files, it stopped working again. So I messed around and I noticed that when I didn't add CSS to make the page pretty that it would work... I kept messing around and I found out that the background-color of the canvas takes away the transparency, it was just that all along... So I just put it on the first canvas, bg, because my page is black and I wanted the canvas to be white.

First step is to wrap your canvases into a container:
<div id="stack">
<canvas id="bg" width="500" height="500"></canvas>
<canvas id="lc" width="500" height="500"></canvas>
<canvas id="rc" width="500" height="500"></canvas>
<canvas id="ch" width="500" height="500"></canvas>
<div>
then properly apply CSS rules:
#stack {
position:relative;
}
#stack > canvas {
position:absolute;
left:0;
top:0;
}
z-index is not necessary here as the first canvas will be at the bottom etc.
Next is to implement a image loader handler as image loading is asynchronous. This is the reason why your image doesn't show as the image hasn't finished loading before calling drawImage() (at the time the code gets to the "fourth" element the image may be loaded depending on various factors such as cache, system performance etc - but this is in the category "random result":
var bg = document.getElementById('bg').getContext('2d'),
lc = document.getElementById('lc').getContext('2d'),
rc = document.getElementById('rc').getContext('2d'),
ch = document.getElementById('ch').getContext('2d'),
img = new Image();
img.onload = drawImgs; /// set handler
img.src = "image.png"; /// set url
function drawImgs() {
/// 'this' is the loaded image
bg.drawImage(this, 0,0);
lc.drawImage(this, 64,64);
rc.drawImage(this, 128,128);
ch.drawImage(this, 192,192);
/// continue rest of code here...
}
If you put your script at the bottom of your page then that's it. If in the header wrap your script in:
window.onload = function() {
... code above here...
}
Other considerations is that your image gets loaded properly. For that you can use the onerror and onabort handlers on the image object:
img.onerror = functionToHandleError;
img.onabort = functionToHandleAbort;
also these defined before setting the src property.

Make sure you use CSS to stack each canvas on top of each other
canvas{position:absolute;border:1px solid red;}
Make sure you give your image time to load
var img=new Image();
img.onload=function(){
bg.drawImage(img,0,0);
lc.drawImage(img,64,64);
rc.drawImage(img,128,128);
ch.drawImage(img,192,192);
}
img.src="img.png";
Here's an example:
<!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; }
#wrapper{position:relative;}
canvas{position:absolute;border:1px solid red;}
</style>
<script>
window.onload=function(){
var ctxs=[];
for(var i=0;i<5;i++){
ctxs.push(document.getElementById("canvas"+i).getContext("2d"));
ctxs[i].fillStyle="black";
ctxs[i].font="12px verdana";
ctxs[i].fillRect(50,i*30+20,100,20);
ctxs[i].fillStyle="white";
ctxs[i].fillText("canvas#"+i,60,i*30+35);
};
}
</script>
</head>
<body>
<div id="wrapper">
<canvas id="canvas0" width=300 height=300></canvas>
<canvas id="canvas1" width=300 height=300></canvas>
<canvas id="canvas2" width=300 height=300></canvas>
<canvas id="canvas3" width=300 height=300></canvas>
<canvas id="canvas4" width=300 height=300></canvas>
</div>
</body>
</html>
One final thought: You might take a quick look at jQuery. It is an excellent utility library that does a great job of solving cross-browser inconsistencies. It is well-tested and in widespread use so your user might already have it cached on their machine.

Canvases can be transparent; I've used this method before. I put up a JSFiddle that you can check to make sure your browser hasn't gone wacky; I'm using the same method you are in your example code, just drawing a square instead of an image. I think the problem is something else.
<canvas id="top" height=100 width=100></canvas>
<canvas id="tall" height=100 width=100></canvas>
<canvas id="short" height=100 width=100></canvas>
<canvas id="bottom" height=100 width=100></canvas>
and JS
var top = document.getElementById("top").getContext("2d");
var tall = document.getElementById("tall").getContext("2d");
var short = document.getElementById("short").getContext("2d");
var bottom = document.getElementById("bottom").getContext("2d");
top.fillRect(0,0,10,10);
tall.fillRect(20,20,10,10);
short.fillRect(40,40,10,10);
bottom.fillRect(60,60,10,10);
To debug, I would just try drawing in each canvas individual, removing the others from your HTML, to make sure that you've got all your references right (it looks like you do.) Then, double-check your CSS and z-index to make sure you're not hiding an element somehow, either by not showing it, or putting its z-index behind another object. Finally, make sure that no other code somewhere is clearing out your canvases, or possibly drawing over your image (if it drew with the same color as your background, it would appear that the canvas was blank, when it was really full of the background color.)

Related

Canvas image is not the same size as the canvas or orginal image

I've put a canvas on top a background image. When I press the 'Try It' button the image appears in the canvas but it does not appear the same size as the parent or fit in the canvas. I only see the top left of the image.
The parent image and the canvas are the same size.
HTML
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" type="text/css" href="style.css">
<script src="script.js"></script>
</head>
<body>
<div class="bg">
<img src="Assets/Images/background.png" alt="background">
</div>
<section class="content">
<p>Image to use:</p>
<img id="taxi" src="Assets/Images/PV.png" width="250" height="300">
<p>Canvas to fill:</p>
<canvas id="myCanvas" width="250" height="300"
style="border:1px solid #d3d3d3;">
Your browser does not support the HTML5 canvas tag.</canvas>
<p><button onclick="myCanvas()">Try it</button></p>
</section>
</body>
</html>
JS
function myCanvas() {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var img = document.getElementById("taxi");
ctx.drawImage(img,10,10);
}
How do I get it so that the image in the canvas is the same size as the parent?
Also, how do I get the image to disappear from the canvas when I press 'Try It' on the second press?
I had the same issue and had to learn the hard way. Responsive Canvas and same same aspect Ratio Canvas is not as easy as one would hope.
What you need to do:
function myCanvas() {
var c = document.getElementById("myCanvas");
var ctx = c.getContext("2d");
var img = document.getElementById("taxi");
ctx.drawImage(img,10,10, 250, 300);
}
Let me explain why.
In your HTML, you have manually declared:
width="250" height="300"
So the image projected on the Canvas needs to be the same size. It is all controlled by the ctx.drawImage(img,10,10, 250, 300) function.
The first argument to the function is the referenced data, this can be a video, image etc.
The second arguments is the X axis offset, the third argument is the Y axis offset. If you want no offset, just pass :
ctx.drawImage(img,0,0, 250, 300);
In this case, the 4th and 5th arguments are the size of the what was passed as first argument.
Here is a codepen, try changing the arguments and see what happens.
PS, you can pass many many more arguments to this method, but usually, this is all you need.
Just wanted to add, you can increase a smaller image to fit a Canvas, and the other way around, but if you declare the size of the Canvas with HTML attributes, and use smaller numbers in the drawImage function, it will not fill the canvas. The HTML seems to have more specificity. This can be good or bad, but it is important to know.

How to create textbox in canvas

I wanted to create text box inside the canvas.
HTML
<canvas id="canvas" width="200" height="50"></canvas>
JavaScript
var input = new CanvasInput({
canvas: document.getElementById('canvas')
});
when I run the file HTML not have anything.
You just simply missed the libraries CanvasInput.min.js simply download from the here and add to your code.
Sample Code:
<html>
<title>sample</title>
<head>
<script src="CanvasInput.min.js"></script>
</head>
<body>
<canvas id="canvas" width="200" height="50"></canvas>
<script>
var input = new CanvasInput({
canvas: document.getElementById('canvas')
});
</script>
</body>
</html>
You cannot simply render a standard HTML input field inside a canvas, if that's what you wanted to achieve.
It looks like you were trying to utilize code from this developer page. But it seems you overlooked that there is a whole lot more Javascript required to simulate an input field as a canvas graphic element. Check out this Git repository to see the whole code.
I made a CodePen showing how to put a text input inside a canvas with this technique. For a quick demo add this script tag to your HTML code (you may want to host the code yourself later):
<script type="text/javascript" src="http://goldfirestudios.com/proj/canvasinput/CanvasInput.min.js?v=1.2.0"></script>

How to use fabricjs

Hy
I'm very new to canvas, I'm trying to learn how to use fabricjs but I can't get even the very basic example to work and it's quite frustrating.
I downloaded the fabricjs-1.4.8.zip file and the only file I'm using is dist/fabric.min.js,
here is my html code
<html>
<head>
<script type="text/javascript" src="jquery-2.1.1.min.js"></script>
<script type="text/javascript" src="fabric.js-1.4.8/dist/fabric.js"></script>
<script tye="text/javascript" src="test.js"></script>
</head>
<body>
<canvas id="myCanvas" width="200" height="100"
style="border:1px solid #000000;">
</canvas>
</body>
</html>
In first place I didn't include jquery, but after seeing many examples looked like that could do the trick, but it didn't for me, maybe I'm including a wrong version?
and this is my test.js file
var canvas = new fabric.Canvas('myCanvas');
// create a rectangle with angle=45
var rect = new fabric.Rect({
left: 100,
top: 100,
fill: 'red',
width: 20,
height: 20,
angle: 45
});
canvas.add(rect);
I can se the border of my canvas element, but no rectangle inside.
Can someone see what I'm doing wrong? thanks
It looks like your canvas is 200 x 100. But you're trying to draw a rectangle 100 pixels from the top. Your code probably works, but the rectangle doesn't show up because it's drawn at the bottom of the canvas. Try changing this line
top: 100
to this:
top: 0
UPDATE
If this doesn't work at first, it could be because the DOM hasn't loaded before your script runs. You can put your code in a jQuery document ready listener like so:
$(document).ready(function(){
//Your code here...
});
This will ensure that the canvas element is actually ready to be used by the time your script fires. Best of luck!

Canvas toDataURL() giving blank image

I'm a complete beginner to JS and I'm just playing around with HTML5. While experimenting, I came across this issue. I have something like this:
<!DOCTYPE html>
<html>
<head>
<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>
<script type="text/javascript">
function graph() {
// ...stuff that draws to canvas, verified "working"...
var downloadLink = document.getElementById("myCanvas").toDataURL();
$("#dlLink").attr("href", downloadLink);
}
$(window).load(function() {
graph();
});
</script>
</head>
<body>
<div class="container">
<h1 style = ";padding-bottom:30px;">Tool</h1>
<canvas id="myCanvas" width="400" height="400"></canvas>
Download
</div>
</body>
</html>
When I click the download link with the base64 encoding, I get a blank image. Can anyone bring to light why this is happening? It seems like the link is generated before the canvas has anything on it, but I can't be sure.
Instead, try this:
$("#dlLink").click(function(){
var win=window.open();
win.document.write("<img src='"+document.getElementById("myCanvas").toDataURL()+"'/>");
});
Try passing toDataURL a content type like "image/png" or "image/jpeg". (canvas.toDataURL("image/png"));

Why is my sprite cropped from the bottom?

I am generating my sprite sheet using Flash Pro and loading the sprite using EaselJS. I am noticing that if my sprite is too large, it gets cropped from the bottom (i.e. the arms get cut out). The following code demonstrates this:
<html>
<head>
<title>Example</title>
<script type="text/javascript" src="easeljs-0.6.0.min.js"></script>
</head>
<body>
<canvas id="canvas">
HTML5 Canvas not supported
</canvas>
<script>
canvas = document.getElementById("canvas");
stage = new createjs.Stage(canvas);
// create spritesheet and assign the associated data.
largeSS = new createjs.SpriteSheet({
images: ["large.jpg"],
frames: [[0,0,221,200,0,0,0],[221,0,221,200,0,0,0],[0,200,221,200,0,0,0],[221,200,221,200,0,0,0]],
animations: {
talk: [0, 3, "talk", 7]
}
});
bmpAnimation = new createjs.BitmapAnimation(largeSS);
bmpAnimation.gotoAndPlay("talk");
stage.addChild(bmpAnimation);
createjs.Ticker.addListener(stage);
</script>
</body>
</html>
The following is my large.jpg:
However, the problem is solved if I make my sprite smaller. Below I have exactly the same code except using a smaller frame size and the same, but smaller, sprite sheet:
<html>
<head>
<title>Example</title>
<script type="text/javascript" src="easeljs-0.6.0.min.js"></script>
</head>
<body>
<canvas id="canvas">
HTML5 Canvas not supported
</canvas>
<script>
canvas = document.getElementById("canvas");
stage = new createjs.Stage(canvas);
// create spritesheet and assign the associated data.
smallSS = new createjs.SpriteSheet({
images: ["small.jpg"],
frames: [[0,0,100,91,0,0,0],[100,0,100,91,0,0,0],[0,91,100,91,0,0,0],[100,91,100,91,0,0,0]],
animations: {
talk: [0, 3, "talk", 7]
}
});
bmpAnimation = new createjs.BitmapAnimation(largeSS);
bmpAnimation.gotoAndPlay("talk");
stage.addChild(bmpAnimation);
createjs.Ticker.addListener(stage);
</script>
</body>
</html>
small.jpeg:
I am really pulling my hair out on this problem. Can someone please explain to me why this happens? What am I doing wrong? Or is there a limit to how large sprites can be?
Thank you.
The default size of the canvas is smaller than your images -- so your image is getting cropped to that. (Chrome is 300x150). Set your canvas height higher, and the rest of your animation will be visible.
Cheers!

Categories

Resources