Make canvas occupy as much space as possible - html

I'm trying to make my HTML5 Canvas occupy as much space as possible. I'm making a game fore Firefox OS that uses the canvas and testing with the Firefox OS simulator.
By "as much space as possible", I mean the whole screen, without scrollbars.
Ideally, a cross-platform way (that also works on Android and iOS) is preferred.

You need to do a few things, set the the canvas position to absolute, and make sure there is no padding, or margins set in the containing element.
The following is what I use in all of my canvas demos
CSS
body, html {
width: 100%;
height: 100%;
margin: 0;
padding: 0;
overflow: hidden;
}
canvas {
position:absolute;
}
JavaScript
var canvas = document.getElementById("canvas"),
width = window.innerWidth,
height = document.body.offsetHeight;
window.onresize = function () {
height = canvas.height = document.body.offsetHeight;
width = canvas.width = document.body.offsetWidth;
};
Full Screen Demo

This should do the trick:
$("canvas").width($("body").width());
$("canvas").height($("body").height());
window.onresize = function(){
$("canvas").width($("body").width());
$("canvas").height($("body").height());
};
Replace canvas with canvas selector. This requires jQuery.

Related

Constantly check screens width/height? (update a function)

I was wondering if there is any way to update a function in javascript for a html site I have.
My code if below and I just want to execute my function constantly. Almost like how the Unity3D game engine has a "void Update()" and what ever is put into it is constantly ran through.
I am using cordova to make my site an app and need to have a way to detect if the device is landscape or portrait.
Thanks!
if(window.innerWidth > window.innerHeight){all of my code....}
This will do it for you, see fiddle https://jsfiddle.net/DIRTY_SMITH/7oe5kh9L/54/
The onresize="myFunction()" is what will trigger the event everytime the page is resized.
javascript
function myFunction() {
var width = window.innerWidth;
var height = window.innerHeight;
if (width > height) {
document.getElementById('test').innerHTML = '<h1>landscape</h1>';
} else {
document.getElementById('test').innerHTML = '<h1>portrait</h1>';
}
}

How can I fix this element to stick at the top of the page on scroll?

I'm working on a project for my UI design class and need help fixing an element to the top of a page on scroll.
Here's what I have so far: http://ieatthings.com/opinio/query.html
As you scroll, the search bar should move up, over the navbar, and fit nicely into place to let the user search while in the middle of a page. But the problem is that the search bar keeps going up!
I used the Javascript from this tutorial: Fix object to top of browser window when scrolling. I have tried all kinds of possibilities and combinations, but have unfortunately not gotten this damn thing to work.
Any suggestions?
You will have to use Javascript to test the position of your element ("myElement") on the page compared to how far the page has been scrolled. If the page has been scrolled up beyond your element then you alter your element's css to snap it to the top of the page. Note: mobile browsers don't like the "position: fixed;" style property.
Give your element the id of "myElement" and insert this into your tag.
<script type="text/javascript">
var yPosition; // save original y position of element here
window.onload = function(){ // once entire page is loaded this function is fired
// save original y position of element before it is scrolled
yPosition = document.getElementById("myElement").offsetTop;
}
window.onscroll = function(){ // scrolling fires this function
var myElement = document.getElementById("myElement"); // for cleaner code
// compare original y position of element to y position of page
if( yPosition <= window.pageYOffset ){
// snap element to the top by changing css values of element
myElement.style.position = "fixed";
myElement.style.top = "0px";
}else{
// re-position to original flow of content
myElement.style.position = "relative";
myElement.style.top = ""; // set to default
}
}
</script>
Hopefully this helps!

HTML5 canvas text resizes

This must be obvious to most of you, so sorry for asking, but how come when I change the width of my canvas my text resizes as well? And how can I prevent this from happening?
code used:
canvas = document.getElementById('canvas');
context = canvas.getContext('2d');
context.fillText("text",10,10);
btw: before I get voted down / bashed at, I tried searching about this for like twenty minutes.. no results.
If you aren't re-sizing it using CSS You need to set the context font like so.
Live Demo
var canvas = document.getElementById("canvas"),
ctx = canvas.getContext("2d");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
function drawText() {
ctx.font = 'italic 20px Calibri';
ctx.fillText("HELLO!", 100, 100);
}
window.addEventListener("resize", function() {
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
drawText()
});
drawText()​
If you are resizing the canvas element using css like the following example
canvas{
width:200px;
}
Then theres not much you can do to fix it. When you resize the canvas using CSS you just stretch it, but the pixel density stays the same. You should never use css to resize the canvas element, rather you should be using the width and height properties via JS like I do in my example above.
This problem might occur due to changing the attributes by using CSS. It seems that canvas gets re-scaled when you access its properties through css. I think your problem might be solved if you use this in your javascript code instead of changing it through css :
document.getElementById("yourCanvasId").height = 150; // height you want to change to
document.getElementById("yourCanvasId").width = 150; // width you want to change to
Same problem occurred with me. I did this and the problem was solved. Hope it helps !

Is there a way to make absolutely positioned divs expand the container?

I have html template - div#container inside body, and some absolutely-positioned divs in container w/o fixed height. Is there a way to expand container to 100% height of page?
Here is an image demostrating my problem: http://habreffect.ru/files/4f3/54ad48420/q.png
I understand, that absolutely positioned divs are "invisible" for container, but unfortunately i got browser window expanded. The problem is, that i can't make body to fit 100% of page, and if I make height:100% of body (and html) it will fit 100% of window height (my is about 900px), but not a page height.
Plz sorry if question is really stupid.
You'll have problems with explorer (can't remember which versions) but you can set
left:0;
right:0;
top:0;
bottom:0;
to expand an absolutely positioned element within a container whose dimensions have been set (in it or in a parent)
The only way I can see is through Javascript
// returns the coordinates of top/left corner of an element
function getPosition(obj)
{
var left = 0;
var top = 0;
if (obj.offsetParent)
{
do
{
left += obj.offsetLeft;
top += obj.offsetTop;
}
while (obj = obj.offsetParent);
}
return {x:left, y:top};
}
document.onload = function()
{
var div = document.getElementById('yourLowestPositionnedDiv');
var divBottom = getPosition(div).y + div.offsetHeight; // y coordinate of the bottom/left corner
document.body.style.height = divBottom - getPosition(document.body).y;
}
This code will expand the size of your body at runtime so that it ends just below your lowest absolute-postioned div.

html5 - canvas element - Multiple layers

Without any extension library, is it possible to have multiple layers in the same canvas element?
So if I do a clearRect on the top layer, it will not erase the bottom one?
Thanks.
No, however, you could layer multiple <canvas> elements on top of each other and accomplish something similar.
<div style="position: relative;">
<canvas id="layer1" width="100" height="100"
style="position: absolute; left: 0; top: 0; z-index: 0;"></canvas>
<canvas id="layer2" width="100" height="100"
style="position: absolute; left: 0; top: 0; z-index: 1;"></canvas>
</div>
Draw your first layer on the layer1 canvas, and the second layer on the layer2 canvas. Then when you clearRect on the top layer, whatever's on the lower canvas will show through.
Related to this:
If you have something on your canvas and you want to draw something at the back of it - you can do it by changing the context.globalCompositeOperation setting to 'destination-over' - and then return it to 'source-over' when you're done.
var context = document.getElementById('cvs').getContext('2d');
// Draw a red square
context.fillStyle = 'red';
context.fillRect(50,50,100,100);
// Change the globalCompositeOperation to destination-over so that anything
// that is drawn on to the canvas from this point on is drawn at the back
// of what's already on the canvas
context.globalCompositeOperation = 'destination-over';
// Draw a big yellow rectangle
context.fillStyle = 'yellow';
context.fillRect(0,0,600,250);
// Now return the globalCompositeOperation to source-over and draw a
// blue rectangle
context.globalCompositeOperation = 'source-over';
// Draw a blue rectangle
context.fillStyle = 'blue';
context.fillRect(75,75,100,100);
<canvas id="cvs" />
You can create multiple canvas elements without appending them into document. These will be your layers:
Then do whatever you want with them and at the end just render their content in proper order at destination canvas using drawImage on context.
Example:
/* using canvas from DOM */
var domCanvas = document.getElementById('some-canvas');
var domContext = domCanvas.getContext('2d');
domContext.fillRect(50,50,150,50);
/* virtual canvase 1 - not appended to the DOM */
var canvas = document.createElement('canvas');
var ctx = canvas.getContext('2d');
ctx.fillStyle = 'blue';
ctx.fillRect(50,50,150,150);
/* virtual canvase 2 - not appended to the DOM */
var canvas2 = document.createElement('canvas')
var ctx2 = canvas2.getContext('2d');
ctx2.fillStyle = 'yellow';
ctx2.fillRect(50,50,100,50)
/* render virtual canvases on DOM canvas */
domContext.drawImage(canvas, 0, 0, 200, 200);
domContext.drawImage(canvas2, 0, 0, 200, 200);
And here is some codepen: https://codepen.io/anon/pen/mQWMMW
I was having this same problem too, I while multiple canvas elements with position:absolute does the job, if you want to save the output into an image, that's not going to work.
So I went ahead and did a simple layering "system" to code as if each layer had its own code, but it all gets rendered into the same element.
https://github.com/federicojacobi/layeredCanvas
I intend to add extra capabilities, but for now it will do.
You can do multiple functions and call them in order to "fake" layers.
You might also checkout http://www.concretejs.com which is a modern, lightweight, Html5 canvas framework that enables hit detection, layering, and lots of other peripheral things. You can do things like this:
var wrapper = new Concrete.Wrapper({
width: 500,
height: 300,
container: el
});
var layer1 = new Concrete.Layer();
var layer2 = new Concrete.Layer();
wrapper.add(layer1).add(layer2);
// draw stuff
layer1.sceneCanvas.context.fillStyle = 'red';
layer1.sceneCanvas.context.fillRect(0, 0, 100, 100);
// reorder layers
layer1.moveUp();
// destroy a layer
layer1.destroy();
but layer 02, will cover all drawings in layer 01. I used this to show drawing in both layers. use (background-color: transparent;) in style.
<div style="position: relative;">
<canvas id="lay01" width="500" height="500" style="position: absolute; left: 0; top: 0; z-index: 0; background-color: transparent;">
</canvas>
<canvas id="lay02" width="500" height="500" style="position: absolute; left: 0; top: 0; z-index: 1; background-color: transparent;">
</canvas>
</div>
I understand that the Q does not want to use a library, but I will offer this for others coming from Google searches. #EricRowell mentioned a good plugin, but, there is also another plugin you can try, html2canvas.
In our case we are using layered transparent PNG's with z-index as a "product builder" widget. Html2canvas worked brilliantly to boil the stack down without pushing images, nor using complexities, workarounds, and the "non-responsive" canvas itself. We were not able to do this smoothly/sane with the vanilla canvas+JS.
First use z-index on absolute divs to generate layered content within a relative positioned wrapper. Then pipe the wrapper through html2canvas to get a rendered canvas, which you may leave as-is, or output as an image so that a client may save it.