ktsangop
ktsangop

Reputation: 1173

Two html canvases on top of each other centered horizontally on browser window

I am trying to use two html5 canvas objects on top of each other, in order to use the one of them as a static background, and the other as a stage that all the action occurs.

The purpose is that the background is larger than the foreground canvas and a static image, so projecting the background once and not rendering it constantly is going to save resources.

I would like both of the objects to be centered horizontally on the center of the browser window always (even if window is resized), and i need some help for the CSS. Currently the two canvases have the same height but not width.

Let me point that the canvases are resized (scaled by height) each time the browser window is resized, so that vertically no part of the scene is clipped/cropped, but horizontally, there is no such restriction. So when the browser window gets smaller in width than the canvases, the get cropped left and right proportionally, and they keep being centered in the middle of the page.

My code is almost complete, as it scales all objects and crops the scene based on the browser window size, but i cannot find a way to center the canvases horizontally.

If you would like to test the code in JS Bin, i would suggest to choose the live preview mode (click the far right arrow button) to see the results in full screen, and play with the window size.

JS Bin code preview

Below are visual results of the current output and the desired one

Current Output

Desired output

Thank you in advance!

Upvotes: 0

Views: 369

Answers (1)

somethinghere
somethinghere

Reputation: 17350

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>

Please keep in mind that I also highly simplified your HTML to just contain the canvasses, this is to avoid any confusion, but the technique should work. Lastyle, when defining a width and height, only use % as a unit, otherwise just use a number as it is automatically going to use pixels. It just looks cleaner.

Like @Rvervuurt said, though, if it's not going use any features of canvas you might as well draw it as a static image and render it as a background-image, centred with background-position: 50% 50% - the overlaying code will still work, but your page will be a little bit snappier as there's no canvas to keep track of at all.

Update: Use <img /> and/or background-image

Below is an implementation of using a simple image or background-image. I have simplified your code a bit (made the canvas simple a drawn square in order for everything to be as obvious as possible).

var cf = document.getElementById('canvas_front');
cf.width = 100;
cf.height = 100;
var ctx = cf.getContext('2d');
ctx.rect(0,0,100,100);
ctx.stroke();
* { margin: 0;padding: 0; }

html, body { height: 100%; }

#canvas_front, #img_back {
  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%);
  z-index: 2;
}
#canvas_back { display: none; }
#img_back { z-index: 1; }
#bg_back {
  position: absolute;
  top: 0;
  left: 0;
  width: 100%;
  height: 100%;
  background-color: yellow;
  background-position: 50% 50%;
  background-size: cover;
  z-index: 0;
}
<!DOCTYPE html>
<html>
<head>
</head>
<body>
  <div id="bg_back" style='background-image: url(https://placeholdit.imgix.net/~text?txtsize=75&bg=880000&txtclr=green&txt=1000×1000&w=1000&h=1000);'></div>
  <img src="https://placeholdit.imgix.net/~text?txtsize=33&txt=A+Large+Background&w=1000&h=800" id="img_back" height="256" width="512" />
  <canvas id="canvas_front" height="256" width="384"></canvas>
</body>
</html>

Upvotes: 1

Related Questions