Optimizing HTML5 Animation - javascript

I have a HTML5 animation that uses a canvas of size 900x520. However ~60% of the canvas is not utilized in the most general case. If some of the parameters of the animation are varied, then the whole canvas is utilized which is the reason why I pegged the maximum canvas size to W:900px and H:520px.
When a user opens the page with this HTML5 canvas, a general case is considered and only 280x280 at the center of the HTML5 canvas is used. As per my knowledge though I'm not using the other 60% of the canvas is not used but is rendered every time which is causing the animation to slow down, especially on tablets and mobile phones (Most of my intended users are tablets / mobile users). So, I would like to know if there are any techniques to render only a set of pixels everytime (say 300x300 at the center of the canvas) ? Are there any workaround solutions ?
I'm already using RequestAnimationFrame (However, I want some more optimization)

First thing i would try is to use the clip() function. It slows down the drawing, but in your case it might be faster to check first against a clip since 60% of the time the clipping will quit the drawing.
Second thing to try is to handle clipping by yourself : handle a viewport object ( center x, center y, width, height ) and exclude unseen object with simple bounding box testing. Rq : Maybe the way you draw your scene allows for easy optimisation.
3) do not define a canvas bigger than the screen : rather define it at max size, and keep track of an offset, like with a viewPort object. And to avoid re-writing all your draw code, just use save/translate/restore before/after your old methods. For the clipping on this canvas, refer to 1) :-)
4) you can reduce graphic strain on mobile by using css scaling. Even if scaling reduces performances, on mobiles it is faster to draw on smaller canvas with a css scale than to draw full resolution with no scale.
So you have to set canvas.style.width and canvas.style.height to some wise values, and you can set canvas.width and canvas.height to the setting that allows for the right performance.

Related

How do I determine the resolution of a computer screen in javascript?

I noticed that the <canvas> element can have different scales. For instance, if I set the CSS width and height to 100px, but have the javascript set the element's width and height to 200px, the element is sized down so everything printed on it is 1/2 the size. (Or 2x the resolution)
I have a retina screen Macbookpro, so in development, I set the scaling to 2x so the images and objects look clear and crisp on my screen.
I have heard that other screens can have a 1.2x resolution (CSS pixels vs Actual pixels)
Is there a way to find out what the resolution/scaling is of the device's screen so I can make my canvas as crisp and as clean as possible to the user?
If it helps at all, I'm trying to make a game in javascript using canvas as my graphics output.
These properties will give your dimensions:
window.screen.availHeight
window.screen.availWidth
For pixel depth, use this property:
window.devicePixelRatio
For application in canvas, a helpful script and explanation is given here.
After searching around using different terms, I was able to find the answer that I was looking for.
The window object has a variable called window.devicePixelRatio. This lets us know the ratio of pixels to the device's screen pixels. On my retina screen, this variable gives me a 2. With this, I can set the canvas to the correct scaling so it looks clean and crisp on any screen.
Source: http://www.html5rocks.com/en/tutorials/canvas/hidpi/

GSAP animations: scale vs height and width

When using GSAP to perform a transition where an element is scaled equally in both dimensions, there seems to be a choice between using scale, or both height and width.
Which is better, as in will result in a higher frame rate? Or if there are conditions on the element / other transitions / DOM / CSS / browser / processor / GPU (/anything else?) that makes one better over the other, what are these?
One of the differences in using Scale Vs Width/Height is the use of CSS but you have to keep in mind while using Scale it will resize from the center of the object, while using Width/Height it will be from top left. Unless you change the transform Origin.
One major factor is the content of the object you are resizing, if you use Scale and the object has content, it will also scale everything inside, while Width/Height will not.
From what I can understand, what scaleX and scaleY do is that they use CSS's transform in the background and generally, using transforms produces a much smoother result because of sub-pixel rendering. Also, if you add force3D: true on the same element as well, it forces it to render it on its own GPU layer hence, hardware accelerated. And that happens because it adds translate3d: (0px, 0px, 0px) onto the same element. So in my opinion, manipulating transform related properties is much better.
Although, this article by Paul Irish
talks about moving elements (i.e. moving with translate vs top and left), but I believe the same holds true in our case.
Here is a quick jsFiddle for you to play around with.

Rendering html canvas images at high resolution

I'm looking to create a system where users create an image in canvas on their browser (with the help of paper.js or processing.js etc) and be able to print a large (up to A3, 300dpi ideally) size representation of what they have created in canvas.
Obviously exporting images straight from the canvas element in the users browser I'm limited to screen size and resolution etc.
So I've looked into the solution of momentarily scaling up the canvas element when the users saves and capturing the image data at the larger size. This could be a solution but I'm pretty sure file size would get out of hand pretty quickly at larger sizes.
I haven't used Node.js very much but was wondering if anyone with experience would know if Node could achieve this and if it would be a better solution and briefly how I'd go about it?
I see two ways to achieve what you want :
use an oversized canvas, that you scale with css.
For instance, you can have a 1000X1000 canvas, that you show within a 200pxX200px smaller view.
<canvas width=1000 height=1000
style = 'width:200px; height:200px;' id='cv'>
</canvas>
use a small canvas for display on screen, and really draw on a backing canvas, that you reproduce on the view canvas at each change.
Both solution cannot solve the issue that mouse coordinates are integer, so to implement a 'pixel perfect' location of object you'll have to implement some kind of zooming. Second solution might be simpler for this.
To retrieve the mouse coordinates, with css scaling do not forget to multiply them by the scale, and in case 2, by the scale you decided.
// formula to get the css scale :
var cssScaleX = canvas.width / canvas.offsetWidth;
var cssScaleY = canvas.height / canvas.offsetHeight;
// then mouse coords are to be multiplied by the scale :
// mouse.x *= cssScaleX;
I tried quickly both solutions, and i was quite surprised to see that css solution is very slow (in both Ch and FF), and it seems faster to copy a back canvas than to have css doing it.
Maybe it depends on some quality settings, but it seems solution 2 is both more flexible and faster.
first css version is here (move mouse to draw 10X10 rect) :
http://jsbin.com/kegohufu/1/
second back canvas + copy version is here (move mouse to draw 10X10 rect) :
http://jsbin.com/qomiqoqi/1/

Scrolling huge backdrop in canvas

My problem is the company I'm working for has started giving me art for the game I'm making for them and it has a huge world! It has given me a huge backdrop image like 12923x5356 huge!
I've now been able to get it to scroll and work like a backdrop but it's a bit slow on my old computer that's an old thinkcenter (note it can only run crunchbang and barely xp). See we want to be able to support tablets for this. It also further complicates things that they have an overlay as well just as big.
Right now I have it only drawing a canvas sized chunk of the backdrop so it only draws as much as can be seen by using
ctx.drawImage(img, x, y, width, height, dx, dy, dwidth, dheight);
with the dx/dy always drawing to the same spot and x/y scrolling with the main character.
Now realistically, is there any way to possibly do this faster? Another way I can think of is to maybe break the image down to small chunks with getImageData and drawing just so many that fills the screen with ctx.putImageData(img, x, y). I'm pretty sure from experience that the small form of drawImage is a bit faster than the long form but would this be much faster?
Anyone else have any ideas they can shoot at me?
You can make it into smaller tiles, just like how Google Maps does.
I'm not sure if you're handling some huge game map, but the technique should be the same. You can split the map into small tiles of, for example, 256px * 256px. Then you only need several 256px * 256px div to cover the viewport. If you use canvas instead, it's the same. Just render those tiles which are currently shown to the user.

iphone/ipad large canvas vs small canvas + div animation

Since I dont have either of these devices handy to test, which method would be faster on an iphone/ipad?
One large canvas (overlayed over a bg of the same size), that is cleared, and has new pixel data drawn to it each frame, at a certain position
or
A small canvas that updates each frame, contained in a div that is animated across a background
As it turns out iphone/ipad aren't even capable of running this small animation either way. I will have to look at alternative solutions for mobile/tablet devices.
Yes, I've found the iPhone too slow in all my canvas experiment.
Even moving a simple div around (CSS3 styled, no canvas) is barely accettable ( my test with the new motion API: http://www.omiod.com/i.htm )

Categories

Resources