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.
Related
I have an interesting problem for a little program I have been developing.
Basically what I wish to create is a window which I can resize but still maintain a 16:9 aspect ratio (note this is for a native application using NWJS). I am also using the easelJS libraries to manipulate the canvas.
The program below basically resizes the canvas to be the same size as the window and does it's job perfectly. But I've been stuck trying to figure out exactly how to maintain the aspect ratio of the window itself.
var stage, w, h;
window.addEventListener('resize', resizeCanvas);
function resizeCanvas() {
w = window.innerWidth;
h = window.innerHeight;
stage.canvas.width = w;
stage.canvas.height = h;
Exactly what sort of calculations do I need to do to force this setting? I'm not as knowledgeable when it comes to things such as aspect ratios.
You should base your calculation on one axis only, and get the new height and width from it.
For a 16/9 ratio
w = window.innerWidth;
h = 9*window.innerWidth/16;
I am working on a multiple web game using JavaScript. My canvas is currently set to the width and the height of my screen.
html
<canvas id = "canvas"></canvas>
javascript
var c=document.getElementById("canvas");
var ctx = c.getContext("2d");
//Making canvas scale;
c.width = window.innerWidth;
c.height = window.innerHeight;
function resize(){
//Add some code
}
My problem is, I do not want my players to zoom out, well not by default. It will make the game look bad and give the players an edge over everyone else. So I need to add some code to go into the resize method, that regardless of scale, the canvas will not be zoomed out. If the end result is something blurry at 300%+ that is fine.
IMPORTANT: the resize function cannot remove or reset the canvas back to default.
There are various ways to scale a canvas.
First off, there are 2 main parameters for the canvas size:
-Canvas Pixel Count. Set via canvas.width = 1000
-Canvas Display Pixel Size. Set via canvas.style.width = '1000px'
If you want all players to see a 1000x1000 region but displaying it fullscreen:
canvas.width = 1000;
canvas.height = 1000;
canvas.style.width = window.innerWidth + 'px';
canvas.style.height = window.innerHeight + 'px';
There is also another option with canvas.style.transform = 'scale(2,2)'.
This method is the closest thing to the browser zoom done via Ctrl+ or Ctrl-.
The big advantage of transform is that the scaling is applied to all DOM children elements. If your game is using HTML for its interface, then this is the way to go. (By applying the scaling on the div containing the canvas + HTML interface.
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;
I have a tricky question that might just have a simple solution, although I trully don't see it now.
So, I've been working around HTML5 element and, obviously, doing the interaction methodology in JavaScript.
One of the objectives of this work is to be able to use a mobile device [MD] (iOS or Android, phone or tablet) as a remote controller for an application that will be served by another machine (eg. a laptop or external display) and both will be showing the same thing on each of the screens on different scales.
So, I wanna have an event occur when the canvas is 80% filled (or in this case, "erased" (which I already have by calculating the total number of [initial] pixels) and each device has a different count since the screen sizes/resolutions are different.
This is the tricky part: How will I be able to "scale" the MD pixel count and mirror that to the bigger screen?
For concrete measures, how will I be able to implement the following example:
I draw a line on the MD that goes for 300px wide, and for simplicity, let's say that this represents 10% of the MD canvas (which on both the screens is in fullscreen).
I want the external monitor (which has a higher resolution) to mirror this event but on an appropriate scale so that those 10% on the MD represent the same (scaled) 10% of "canvas real estate"
Just in case the text is too confusing, I'll leave the code bellow:
function totalPix(x, y) {
var total = x * y;
var objective = (total * 80) / 100;
}
function canvasApp() {
//prevent from scrolling (no bouncing)
document.body.addEventListener('touchmove', function(event){
event.preventDefault();
}, false);
if(!canvasSupport()) {
alert("No canvas support on this device!");
return;
} else if(!socketSupport) {
alert("No websocket support on this device!");
} else {
//create canvas on every load (//TODO)
var elemDiv = document.getElementById("content");
var newElem = document.createElement("canvas");
newElem.setAttribute("id", "frontscreen");
elemDiv.appendChild(newElem);
drawScreen();
function drawScreen() {
//Setup canvas
var canvas = document.getElementById("frontscreen");
canvas.width = window.innerWidth;
canvas.height = window.innerHeight;
totalPix(canvas.width, canvas.height);
ctx = canvas.getContext("2d");
ctx.fillStyle = "black";
ctx.fillRect(0, 0, canvas.width, canvas.height);
ctx.beginPath();
//Foreach touchmove event, send position to server
canvas.addEventListener('touchmove', function(event) {
for (var i = 0; i<event.touches.length; i++) {
var touch = event.touches[i];
ctx.globalCompositeOperation = "destination-out";
ctx.fillStyle = "white";
ctx.beginPath();
ctx.arc(touch.pageX, touch.pageY, 30, 0, 2*Math.PI, false);
ctx.fill();
ctx.stroke();
}
}, false);
window.onresize = function resizeCanvas() {drawScreen();};
}
}
}
If I understand you correctly, it's as simple as changing the size property on the HTML style property of your <canvas> element. For example, let's say you fill in a 300 by 300 px. square on Monitor A, which occupies 10% of the screen real estate (I know, big monitor). Then you load the same page on Monitor B, which is twice the size of Monitor A. (Really really big monitor, just bear with me here. It's an example.) Naturally, it will only occupy 5% of the screen's real estate.
If you want that 300px to always occupy the same percentage of size on all screens (but still be 300px on the canvas), you can do something like this:
var canvas = document.getElementById("mycanvas");
var heightAsPercent = 10;
var widthAsPercent = 10;
canvas.style.height = (heightAsPercent / 100) * screen.height;
canvas.style.width = (widthAsPercent / 100) * screen.width;
That way, the canvas will always occupy 10% of the screen, whether the monitor width is 3000px or 6000px. I've obviously chosen very verbose variable names for clarity, so feel free to modify them as needed.
The reason this works is that you're only modifying the CSS properties of the canvas, which affect only how it's rendered, not the actual <canvas> data. I came across this little trick by accident, and it drove me nuts until I figured out why it was doing this. Now it actually comes in handy. :)
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);
}
}