12

I'm writing a Phonegap (3.2) app, I take a HTML5 canvas, make it full screen and the whole app UI is on this canvas.

Using a Samsung Galaxy S4 (Android 4.3) to test the app, the screen resolution of the app is only 360X640 and not 1080X1920 like I want it to be.

What is needed to be done in-order to make the app use the maximum possible screen resolution ?

I've added screen shots 1) // Looks OK but bad resolution

windowWidth = window.innerWidth; windowHeight = window.innerHeight; enter image description here

2) // Takes small part of the screen, rest is white

windowWidth = window.outerWidth; windowHeight = window.outerHeight; enter image description here

3) // Only a small part of the picture is visible, as if the image is at 1080X1920 but the screen is 'too small' for it.

windowWidth = screen.width; windowHeight = screen.height; enter image description here

and here is the full code:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="utf-8" />
    <title>PhoneGapTesting</title>
    <script type="text/javascript" src="js/jquery.min.js"></script>
    <script type="text/javascript" charset="utf-8" src="cordova.js"></script>
    <!-- -->
    <script type="text/javascript">

    var windowWidth;
    var windowHeight;

    var canvasMain;
    var contextMain;

    var backgroundImage;

    $(document).ready(function() {
        windowWidth = window.innerWidth;
        windowHeight = window.innerHeight;
        //windowWidth = window.outerWidth; // Only 'window.innerWidth' + 'window.innerHeight' look OK but not max resolution
        //windowHeight = window.outerHeight;
        //windowWidth = screen.width;
        //windowHeight = screen.height;

        canvasMain = document.getElementById("canvasSignatureMain");
        canvasMain.width = windowWidth;
        canvasMain.height = windowHeight;
        contextMain = canvasMain.getContext("2d");

        backgroundImage = new Image();
        backgroundImage.src = 'img/landscape_7.jpg';
        backgroundImage.onload = function() {
            contextMain.drawImage(backgroundImage, 0, 0, backgroundImage.width, backgroundImage.height, 0, 0, canvasMain.width, canvasMain.height);
        };

        $("#canvasSignatureMain").fadeIn(0);
    })

    </script>
</head>
<body scroll="no" style="overflow: hidden">
    <center>
        <div id="deleteThisDivButNotItsContent">
            <canvas id="canvasSignatureMain" style="border:1px solid #000000; position:absolute; top:0;left:0;"></canvas><br>
        </div>
    </center>
</body>
</html>

Thanks.

Miko Diko
  • 944
  • 1
  • 13
  • 33

3 Answers3

22

A solution that is working with both resolution and touch event issue (that came with Ken's post):

<meta name="viewport" content="user-scalable=no, initial-scale=1, maximum-scale=1, minimum-scale=1, width=device-width, height=device-height, target-densitydpi=device-dpi" />

In the < head >

Thanks Ken for trying to help bro :))

Miko Diko
  • 944
  • 1
  • 13
  • 33
12

Try something like this:

var windowWidth = window.innerWidth;
var windowHeight = window.innerHeight;
var pixelRatio = window.devicePixelRatio || 1; /// get pixel ratio of device

canvasMain = document.getElementById("canvasSignatureMain");

canvasMain.width = windowWidth * pixelRatio;   /// resolution of canvas
canvasMain.height = windowHeight * pixelRatio;

canvasMain.style.width = windowWidth + 'px';   /// CSS size of canvas
canvasMain.style.height = windowHeight + 'px';

(or an absolute value for the css rule).

On devices where the pixel ratio is higher than the typical 1:1 you get a higher resolution canvas. For normal circumstances everything is as normal.

  • 1
    You were close :), It works if I: canvasMain.style.width = "360px"; /// CSS size of canvas canvasMain.style.height = "640px"; – Miko Diko Dec 11 '13 at 06:33
  • @MikoDiko yeah, I forgot to set px at the end there, thanks :) –  Dec 11 '13 at 07:50
  • 1
    Now I'm into a new problem, when there is a touch-event on this canvas, I get coordinates of a 360X640 screen and not 1080X1920. the max X is 360 .. not 1080. Do you maybe know how to fix this ? – Miko Diko Dec 11 '13 at 08:21
  • @MikoDiko it's on of the problems with scaling canvas width css (which is necessary here). You simply scale the coordinate x/y up by using the ratio or create a ratio by dividing real canvas size on display size. Hope this helps. –  Dec 11 '13 at 09:23
  • Yes I thought about it, but I have a drawer, and it's a big problem when drawing 'almost straight' lines, cause the minimum curve is 'pixelRatio' and not simply 1.. There has got to be a good solution – Miko Diko Dec 11 '13 at 10:40
  • This is not a good solution. A canvas's context2D, when pixel ratio is 2, has already the right resolution. By doubling it again, you end up wasting performances and memory, by a 4X factor (each points has 4 backing points). The right solution is to have at hand a double sized image that you draw with a (0.5, 0.5) scale, to reach the 'subpixels' of the canvas. – GameAlchemist May 12 '14 at 02:00
  • Notice also that 1) you deal with pixelRatio but not backingStoreRatio, that is used on some famous devices, and that 2) those ratios might be non-integers (1.2 for instance), so you need to round width/height to get valid values for both canvas and css (but anyway you shouldn't use css as told above). – GameAlchemist May 12 '14 at 02:11
1

window.innerWidth and window.innerHeight don't necessarily give you the real screen dimensions.

Try this instead:

windowWidth = window.screen.innerWidth; 
windowHeight = window.screen.innerHeight; 

target-densitydpi in the meta tag in Miko's post is deprecated in Chrome and should not be used.

Instead, try the following:

index.html:

<meta name="viewport" content="initial-scale=1 maximum-scale=1 user-scalable=0 minimal-ui" />

You should also consider using Phaser's methods for scaling, like this:

Boot.js:

var game = new Phaser.Game(1080, 1920, Phaser.CANVAS, ''); //or AUTO mode for WebGL/DOM

For performance, use the smallest dimensions that you can regardless of the device's resolution. Let Phaser create the canvas object.

Game.js:

this.scale.scaleMode = Phaser.ScaleManager.EXACT_FIT; //or SHOW_ALL or RESIZE
this.scale.pageAlignHorizontally = true;
this.scale.pageAlignVertically = true;

Your entire canvas will scale automatically by the ScaleManager, but this slows the app down when performance is needed -- especially with a large canvas. EXACT_FIT will stretch the canvas, while SHOW_ALL will resize it so that the whole canvas fits onto the screen without changing its aspect ratio (which can leave margins like the one you have).

Victor Stoddard
  • 3,582
  • 2
  • 27
  • 27