I have an iPad 2 canvas app (game) and would like to get it to run on the new iPad retina display.
Simply put, what is the best method to stretch/shrink my iPad2 image for retina iPad models?
From the googling I've done, I've seen various methods but many include starting with retina sized images and scaling done.
I've also heard the performance of pushing retina quality sized pixels to the screen is slow, and that it is better to use iPad size images at the expense of some quality.
As it is right now, on the new iPad I see the top left quarter of my app, which makes sense, but performance is shocking compared to iPad 2.
Techniques I've seen include CSS media queries, using the pixel density, and CSS transforms - which are apparently quite fast.
Thanks
I've put together a simple function to handle this problem. Basically, it takes the current canvas size and scales it by the device-pixel-ratio, shrinking it back down using CSS. It then scales the context by the ratio so all your original functions work as usual.
You can give it a shot and see how performance fares. If it isn't what you hoped for, you can just remove it.
function enhanceContext(canvas, context) {
var ratio = window.devicePixelRatio || 1,
width = canvas.width,
height = canvas.height;
if (ratio > 1) {
canvas.width = width * ratio;
canvas.height = height * ratio;
canvas.style.width = width + "px";
canvas.style.height = height + "px";
context.scale(ratio, ratio);
}
}
Related
So I am trying to learn javascript by making a game where you click on a canvas to move a circle and you have to dodge multiple other circles coming in your direction. I am close to the final result but I just realized that the larger your screen is, the easier it is for you to play.
The reason is that the enemies spawn at the edges of the canvas, so if the canvas is bigger, you have more time to react to them since their speed doesn't change. The game is supposedly refreshing around 60fps and each time it resizes the canvas depending on if you change your window size. The only thing I can think of is increasing the speed of enemies with the size increase but I don't know if there's any other way to go about this. Maybe I could increase the size of the of the player and the enemies to accommodate the change in window size but I don't know which is better or how to make sure I am consistent with the ratio increase.
Any suggestions would be much appreciated. Thanks for your time
Here's my full code: https://jsfiddle.net/r2f6eb89/2/
It doesn't actually run on this site so it's just a reference for my logic.
Here are the resizing functions:
/*
function setCanvasSize() {
//c.width = window.innerWidth-100;
//c.height = window.innerHeight-100;
if (window.innerWidth < window.innerHeight) {
c.width = window.innerWidth - 150;
c.height = window.innerWidth - 150;
} else {
c.width = window.innerHeight - 150;
c.height = window.innerHeight - 150;
}
}
*/
function setCanvasSize() {
c.width = 600;
c.height = 600;
}
There's actually two kinds of "width" and "height" property. One is the width and height you can actually see in your website, that is, the one you can change by the property on your html file element. The other one is the width and height you set in the javascript file, for setting the coordinate you use to print image or draw in the canvas.
Example for first type of the width/height property:
<canvas id="my_canvas" width="500" height="200"></canvas>
Example for second type of the width/height property:
var canvas = document.getElementById("my_canvas");
canvas.width=500;
canvas.height=200;
It seems like you are changing the second type of the width/height property each refresh. If that's not what you want, try modifying the first type of width/height. It seems like a simpler solution to your question. To modify the first type of property, the CSS property in javascript, here's the code:
canvas.style.width="500px";
canvas.style.height="200px";
Hope that helps :)
I'm working on a sketchpad application using html canvas and javascript (trying to stay away from jQuery). The canvas needs to be responsive and I've found several methods to do so, but each one stretches out the canvas and makes the sketchpad unusable. It's hard to explain without seeing the problem. Here's the CodePen. Try drawing inside the canvas and you'll see what I'm talking about. The current method I'm using to resize the canvas incorporates offsetWidth and offsetHeight like so:
var sketchpadContainer = [
document.getElementById('container').offsetWidth,
document.getElementById('container').offsetHeight]
var canvas = document.getElementById('sketchpad');
canvas.style.height = sketchpadContainer[1] + "px";
canvas.style.width = sketchpadContainer[0] + "px";
Is there a way to make the canvas responsive while at the same time keeping the dimensions of the sketch intact?
The CSS width and height properties are NOT the same as the width and height attributes on a Canvas element.
If you absolutely need to use css to set width/height, keep a scale factor of your default canvas size, then multiple the target x and y positions of your mouse position by the inverse of the x/y scale factors (or just divide the target position by them).
Using css to resize your canvas is a bit too hacky imo (and will leave your lines blurry), I highly recommend you instead simlpy change with width/height attributes of your canvas and use CanvasRenderingContext2D.scale() to change the size of your lines (A scale factor will still need to be used to calculate your true mouse pos, however)
Simply change
canvas.style.height = sketchpadContainer[1] + "px";
canvas.style.width = sketchpadContainer[0] + "px";
to
canvas.height = sketchpadContainer[1];
canvas.width = sketchpadContainer[0];
Apply CanvasRenderingContext2D.scale() when you first get your context, and then do as I mentioned above. (ctx.lineTo(x,y); -> ctx.lineTo(x/scaleFactorX,y/scaleFactorY); & lastX=x; -> lastX=x/scaleFactorX;)
I.E See HERE
I have a 960px width and 960px height html5 canvas game. I use Javascript to resize the canvas and rescale its content proportionally to always fit the window vertically (and horizontally too) so the bottom is never cut off since many screens are less than 960px high and some users don't even know they can zoom out with a desktop browser to fit the content. The code is:
var w = stage.canvas.width;
var h = stage.canvas.height;
var scaleFactor;
window.addEventListener('resize', resizeCanvas, false);
function resizeCanvas() {
scaleFactor = Math.min(window.innerWidth / w, window.innerHeight / h);
stage.canvas.width = scaleFactor * w;
stage.canvas.height = scaleFactor * h;
stage.scaleY = scaleFactor;
stage.scaleX = scaleFactor;
}
My problem is the game also resizes itself when I zoom either in a desktop or in a mobile browser since zooming also changes window.innerWidth and window.innerHeight values. HOWEVER, I want the game to only resize itself when the window is resized but still be able to be zoomed (especially in small mobile screens) for people whose eyes are not so perfect.
I've been searching and trying different methods for weeks now, but I still haven't found any solutions. I would be very happy if someone could come up with a not-so-complicated solution since I'm relatively a beginner.
When zooming in and out, the devicePixelRatio value does change.
So you can save this value at init and check if it has changed in the resize event to determine if the event was triggered by an actual resizing of the window, or by zooming.
let dpr = window.devicePixelRatio;
onresize = e => {
if(window.devicePixelRatio !== dpr){
log.textContent = 'zoom event';
dpr = window.devicePixelRatio
}
else{
log.textContent = 'resize event';
}
};
<pre id="log">Please see in full-page.
Then, either zoom or resize the window</pre>
Or as a fiddle.
I am making a whiteboard with angularjs, socketio an node.js.
As long as I use a fixed width/height for the canvas everywhere I can just broadcast the coordinates of the mouse/touch event and recreate the graphic in realtime. However, the problem I am facing is when trying to make the canvas have different sizes across different platforms (think desktop and a smartphone), the canvas has to be scaled and so does the graphic, but this makes things pretty slow.
The approach I am currently taking is to draw the graphic in a temporary hidden canvas of original size, then when there is a pause in the drawing stream (in other words the user has stopped doodling), I scale and copy it to the main canvas. The problem with this is, it doesn't feel very realtime at all, especially when a user keeps doodling without a pause for a while. Another approach I could try is to push all the coordinates in an array, apply 2d affine transformation on it, then redraw the entire thing. Though this too doesn't seem like a good solution for when the array size increases, repeatedly trying to apply transformations in realtime can easily eat up a lot of resources.
Is there any better way to achieve this?
do it with css scale transform. Scale the canvas to fit the size of the device be it a mobile, desktop, or tablet, or whatever.
Have your canvas be fixed width across all devices. Say it's 640px by 480px. Now we'll resize it to fit whatever window.
$(window).resize(function() {
var w = 640; // $('#mycanvas').width();
var h = 480; // $('#mycanvas').height();
var newWidth = $(window).width(); // this could be either smaller or bigger than the canvas
var newHeight = $(window).height(); // same here
var scaleX = newWidth / w;
var scaleY = newHeight / h;
$('#mycanvas').css('transform','scale(' + scaleX + ',' + scaleY +')');
$('#mycanvas').css('-webkit-transform','scale(' + scaleX + ',' + scaleY +')');
});
note: mycanvas could also be a container if any kind that holds the canvas and other divs or whatever. just make sure that w is the width of that container, etc.
note: if someone uses their fingers to draw across the screen, you may need to convert it from scaled coordinates to fixed width (640x480) coordinates.
Btw, I found a different way to do this that might be better. not sure:
Scaling canvas element with static resolution
I'm trying to design a web using flex-boxes in order to fit it to any kind of screen size. My main screen has a canvas, so... which is the best way to resize the canvas during the inizialitation?
I have tried these two ways. My first way was to use CSS and set a percentage for its size. For example, width=100% and height=100%. Despite the design worked, I found that there were a lot of issues when playing with the coords of my canvas. For example, when dragging an item, my mouse coords where amplified by ten times or so.
Despite I could manage that, I think it's not the best approach.
The second way was to set a fixed size when the onload and onresize events when they are fired. I was doing something like this:
window.initHeight = window.screen.height;
window.initWidth = window.screen.width;
/*The height of the navbar.*/
navbar.height = document.getElementById('navbar').offsetHeight;
canvas = document.getElementById('canvasStage');
canvas.width = window.initWidth;
canvas.height = window.initHeight - navbar.height;
canvas.setAttribute("width", canvas.width);
canvas.setAttribute("height", canvas.height);
The problem is that the height seems to be too big:
http://i.imgur.com/WI0jGH2.png
How could I fit the screen exactly through this way?
The third way, but I'll try to avoid it, is to set a fixed size and let the small screens to scroll on the page.
Thanks!
UPDATED:
This is my JSFiddle:
http://i.imgur.com/NRTykLv.png
window.screen.width and window.screen.height returns the width and height of the screen which includes all bars (evrything you see on your screen).So you have to use window.innerHeight and window.innerWidth in order to get the view port height and width
Replace
window.initHeight = window.screen.height;
window.initWidth = window.screen.width;
with
window.initHeight = window.innerHeight;
window.initWidth = window.innerWidth;