How can I stack two same-sized canvas on top of each other?
Use CSS's position: absolute
. Add the following CSS to your page:
canvas {
position: absolute;
top: 0;
left: 0;
}
This will put both canvases at the same spot: the topleft-most part.
You might want to put them in a wrapper element, which will need to be position: relative
in order for its child elements to be. For example, your HTML will look something like this:
<div class="wrapper">
<canvas id="canvas1" width="400" height="300"></canvas>
<canvas id="canvas2" width="400" height="300"></canvas>
</div>
And your CSS will look like this:
.wrapper {
position: relative;
width: 400px;
height: 300px;
}
.wrapper canvas {
position: absolute;
top: 0;
left: 0;
}
Then position the wrapper div however you'd position the other stuff.
Placing two canvas elements on top of each other
Actually I am not sure why your version does not work (it should as-is!), but here's a version that uses your code and a bit of CSS to check the overlap. Read the comments in the CSS. When done, remove the extra code and enable .wrapper canvas { top: 0 }
again.
Without the Javascript, I might add, I don't use Django.
However, it seems your JS new Image()
has no size parameters and ctx.drawimage
only has a location (0,0) but no (height,width) to work with.
So, height=0, width=0 yields nothing to overlap...
Forgot to mention: give both canvas
a z-index
so you can control which is on top.
UPDATE
Added Javascript and a third canvas
to prove the code works as expected. Also inserted z-index
per canvas as suggested before. Retrieving a few random pics from 'Lorem Picsum' to fill the canvas.
NOTICE that I use proper width/height parameters in my Javascript....
var canvas1 = document.getElementById("dorsal") , ctx1 = canvas1.getContext("2d");var canvas2 = document.getElementById("dorsal-duplicate"), ctx2 = canvas2.getContext("2d");var canvas3 = document.getElementById("extra-img") , ctx3 = canvas3.getContext("2d");
var background1 = new Image(512,256);var to_draw_on = new Image(512,256);var extra_img = new Image(512,256);
background1.src = "https://picsum.photos/512/512?random=0";to_draw_on.src = "https://picsum.photos/512/512?random=1";extra_img.src = "https://picsum.photos/512/512?random=2";
background1.onload = function(){ctx1.drawImage(background1,0,0);}to_draw_on.onload = function(){ctx2.drawImage(to_draw_on,0,0);}extra_img.onload = function(){ctx3.drawImage(extra_img,0,0);}
/* code to draw on the second canvas */
.wrapper {position: relative;width : 512px;height: 512px;}
.wrapper canvas {position: absolute;left: 0;/* top : 0; /* temporary disabled */
/*ADDED*/width: 100%; height: 100%; /* fill-parent */border: 2px dotted black;}
/* To check the overlap: - make #dorsal fill the top half of 512px - make #dorsal-duplicate fill the bottom half of 512px*/#dorsal { top : 0; height: 50%; background-color: green; z-index: 1;}#dorsal-duplicate { background-color: red; bottom: 0; height: 50%;
z-index: 2;}#extra-img { background-color: blue; left: 64px; bottom: 128px; height: 50%; width: 75%;
z-index: 3;}
<div class="wrapper"> <div class="pb-2 justify-content-center"> <h2> <strong>Drawing test</strong> </h2> <p>removed width/height values from <canvas>, redundant. <div class="justify-content-center"> <form enctype="multipart/form-data" method="post" action="">{% csrf_token %} <div class="wrapper"> <canvas id="dorsal" ></canvas> <canvas id="dorsal-duplicate"></canvas> <canvas id="extra-img" ></canvas> </div> </form> </div> </div></div>
How can I stack two same-sized canvas on top of each other, next to another canvas?
Use a container div that is positioned relative that will contain the canvas elements positioned absolute.
<div style="width: 810px; margin-left: auto; margin-right: auto;">
<canvas width="350" height="350" id="imageCanvas" style="float: left; border: 1px solid black;"></canvas>
<div class="container">
<canvas width="350" height="350" id="plotCanvas" style="margin-left: 6px; border: 1px solid black;"></canvas>
<canvas width="350" height="350" id="plotCanvas_BG" style="margin-left: 6px; border: 1px solid black;"></canvas>
</div>
</div>
CSS
.container {
display: inline-block;
position: relative;
float: left;
}
#plotCanvas,
#plotCanvas_BG {
position: absolute;
top: 0;
left: 0;
background-color: transparent;
}
#plotCanvas {
background-color: #fff;
}
JSFiddle Demo: https://jsfiddle.net/8c8csnzk/1/
How do I center two canvases on top of one another?
Make an outer container with text-align:center
and position:relative
, make an inner container with position:relative
, put the canvases inside the inner container, remove left:0;top:0;
on both canvases, and remove the position:absolute
on the lower of the canvases. And make sure in the html that the lower canvas comes before the upper canvas, like you have.
#container {
text-align:center;
position:relative;
}
#inner_container{
position:relative;
}
#upper {
z-index: 1;
}
#lower {
position:absolute; z-index: 0;
}
http://jsfiddle.net/NW6Fx/
Edit: I believe the z-index property isn't needed if you do it this way. The order is just a matter of which canvas comes first in the html and which is position:relative
.
Two html canvases on top of each other centered horizontally on browser window
The following works, and I'm including a snippet implementation below.
canvas#front, canvas#back {
position: absolute;
/* Use calc to make sure that browser without transform support
* (that therefore also dont support calc) don't
* actually move your elements. */
left: calc(50%);
top: calc(50%);
/* Don't forget to prefix. */
transform: translate(-50%,-50%);
z-index: 1;
}
canvas#back { z-index: 0; }
document.documentElement.style.overflow = 'hidden';window.addEventListener('resize', function(){resizeCanvas();}, true);
var sscale = 1.0;canvas_back = document.getElementById("canvas_back");stage2 = new createjs.Stage(canvas_back); stage2.autoClear = true;my_ticker2 = createjs.Ticker.on("tick",stage2); this.back = new createjs.Bitmap("http://i.imgur.com/VcDqpBW.png"); stage2.addChild(this.back); canvas_front = document.getElementById("canvas_front");stage = new createjs.Stage(canvas_front); stage.autoClear = true;createjs.Ticker.timingMode = createjs.Ticker.RAF_SYNCHED; createjs.Ticker.framerate = 120;my_ticker = createjs.Ticker.on("tick",stage); this.ob1 = new createjs.Bitmap("http://i.imgur.com/3toyiJo.png"); this.ob1.x=Math.floor(canvas_front.width/2); this.ob1.y = Math.floor(canvas_front.height/2);stage.addChild(this.ob1);resizeCanvas();
function resizeCanvas(){ var SCREEN_WIDTH = window.innerWidth; var SCREEN_HEIGHT = window.innerHeight;//window.screen.availHeight; console.log("SCREEN_WIDTH, SCREEN_HEIGHT, canvas_back.height", SCREEN_WIDTH, SCREEN_HEIGHT, canvas_back.height); ratio = (SCREEN_HEIGHT/canvas_back.height);
sscale = (sscale*ratio); console.log("ratio,sscale : ", ratio,sscale); stage.scaleX = sscale; stage.scaleY = sscale; canvas_back.width = Math.min(canvas_back.width*ratio); canvas_back.height = Math.min(canvas_back.height*ratio); console.log("canvas width/height : " , canvas_back.width, canvas_back.height); stage2.scaleX = sscale; stage2.scaleY = sscale; canvas_front.width = Math.min(canvas_front.width*ratio); canvas_front.height = Math.min(canvas_front.height*ratio); /*if(canvas_back.width > SCREEN_WIDTH) { */ console.log("canvas width bigger than screen width"); document.documentElement.scrollLeft = ((document.body.scrollWidth - document.body.clientWidth) / 2); document.body.scrollLeft = ((document.body.scrollWidth - document.body.clientWidth) / 2); /*}*/}
*{ margin: 0; padding: 0;}
html, body { height: 100%;}
#canvas_back, #canvas_front { position: absolute; left: 50%; top: 50%; -webkit-transform: translate(-50%, -50%); -moz-transform: translate(-50%, -50%); -ms-transform: translate(-50%, -50%); transform: translate(-50%, -50%);}
<!DOCTYPE html><html><head> <meta charset="utf-8"> <title>JS Bin</title> <script type="text/javascript" src="https://code.createjs.com/createjs-2015.05.21.min.js"></script></head><body> <canvas id="canvas_back" height="256" width="512"> asdf </canvas> <canvas id="canvas_front" height="256" width="384"> asdf </canvas></body></html>
Stacking multiple canvases in HTML5
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.
Related Topics
Can You Overlay a Transparent Div on an Image
Correct Way for Writing an <Address> Tag for My Web Site, to Provide Contact Details for Our Company
How to Make a Div Grow in Height While Having Floats Inside
How to Fix Background Image Inside Div
Div with 100% Width of Screen, But Inside a Parent Div with Fixed Width
CSS Specificity - External Style Sheet Vs Internal Style Sheet Using Just Classes
Susy, Media Queries, and Lt Ie9
CSS - Make Span Extend to End of Its Container/Fill Empty Space
How Do Display a Boostrap/Angularui Alert Always on Top
Avoid an Image to Go Outside a Div
Two Divs; Left Should Be Fixed Width, Right Should Fill Rest of Space
How to Change a Div Padding Without Affecting The Width/Height
Applying a Stylesheet Within One Div Only
How to Print a Web Page with All Its CSS Style Attached to The Page
React Bootstrap - How to Center Image Vertically in a Row
Hide-Nav-Bar Hides Nav-Buttons Too. I Want to Retain The View Title and The Ion-Nav-Buttons