Context: I'm using window.devicePixelRatio to determine the display resolution for a few canvases on a website.
To the best of my knowledge, the DPR value should change when zooming in and out on a website. This is what happens on Chrome. But it doesn't seem to happen in Safari. Querying the value of window.devicePixelRatio or devicePixelRatio from the JS Console always returns the same value, no matter how much I zoom in or out. I've tried this on three separate computers, all of them Macs running either Safari v13.1.2, v14.1.2, or v15.1.
The MDN Web Docs page on Window.devicePixelRatio implies that the DPR should change on zoom, both in its definition at the top and in its example code. The spec linked by MDN says the following (bolded emphasis mine):
The devicePixelRatio attribute must return the result of the following determine the device pixel ratio algorithm: If there is no output device, return 1 and abort these steps. Let CSS pixel size be the size of a CSS pixel at the current page zoom scale factor and at a pinch zoom scale factor of 1.0. Let device pixel size be the vertical size of a device pixel of the output device. Return the result of dividing CSS pixel size by device pixel size.
Should Safari's window.devicePixelRatio be changing on zoom? If the DPR doesn't change with zooming, is there a different way to determine a good canvas display resolution on Safari?
This is my first question on StackOverflow so please let me know if anything can be improved.
Related
I am trying to obtain the screen scaling on the client machine - the value in the image below. As you can see it's set to 150%.
I've tried window.devicePixelRatio, which returns 1.5 - which is what I want, but only if the browser zoom is at 100%. I am unclear how to get zoom level in a modern browser, which precludes me from getting accurate screen scaling.
Am I missing a simple way to obtain screen scaling?
P.S. This question doesn't solve anything because the ratio as the same as zoom, which makes it impossible to find the scaling. See example.
I'm trying to programatically determine the zoom level in IE 11. Researching this, I've seen that Chrome and Firefox report the "actual" window.outerWidth independent of the "zoomed" window.innerWidth values - allowing for a calculation to determine zoom level. But IE 11 reports both values as having changed (outerWidth also changes when zoomed). Is there some object in IE that can be queried for "actual" window width? Or perhaps some trick to create an object that doesn't zoom when the page does? I just need something reporting dimensions independent of the zoomed content.
So I decided to just use a transparent png with a fixed px width in comparison to window width, should serve my purpose.
This question already has answers here:
Display pixel-perfect canvas on all devices
(3 answers)
Closed last month.
Is it possible to set the size of the bitmap in an HTML5 canvas so that it exactly matches the display size in device pixels, ie the number of physical pixels used to display the canvas, even when window.devicePixelRatio is not an integer?
There is a good description of how to resize the canvas on webglfundamentals but it does not properly handle non-integer devicePixelRatios. My understanding so far:
The display size of the canvas is set in CSS with, eg, canvas {width: 200px;}.
The underlying bitmap size is set with, eg, <canvas width="100"/> in HTML or canvas.width = 100 in JS.
The bitmap will be stretched to fit the CSS size (how is affected by object-fit and object-position).
We can set bitmap size to be equal to some expression involving canvas.clientWidth.
canvas.clientWidth is an integer and its unit are CSS pixels and is the calculated width of the content (plus padding). I don't know if the browsers actually draw the content into a whole number of CSS pixels or a whole number of device pixels.
So webglfundamentals suggests something like
canvas.width = Math.floor(canvas.clientWidth * window.devicePixelRatio);
but if window.devicePixelRatio is a fraction, this sometimes doesn't work (2 pixel wide lines drawn on integer coordinates are fuzzy). My 1920x1080 screen has devicePixelRatio of 1.5 by default, and page zoom can affects this, so lots of reasons why devicePixelRatio is not an integer as a rule. What can we do?
1px is a logical length unit in CSS/DOM realm. Dot.
So I don't think that you will find reliable method for getting physical pixels. Check this.
That's why in Sciter I've made px units to represent always physical pixels of the device. And introduced dip units that are logical pixels - 1/96 of inch measured by the ruler on device surface (so 1dip ~ 1px of W3C CSS).
I simply do not understand how to do serious UI development without the ability to define objects in device pixels.
I know this is an old thread, but I hope I can help a bit any other wanderer coming to this.
There is a way to make a "canvas pixel" match "device pixel" as close to a 1:1 ratio as possible, at least from my experience while making a Canvas WebGL based game engine, even with non-integer devicePixelRatio values.
First, there are 3 things we need to understand:
CSS Size: Refers to the actual Canvas DOM element size in CSS pixel (px) units.
Canvas Size: Logical size of the canvas, as set using the element properties (i.e. canvasElem.width = 100;), this affects your render space.
Device Pixel Ratio: Value obtained from window which effectively describes the ratio between a physical pixel and a CSS pixel.
Brief Example
Let's say you have a devicePixelRatio of 2.625, and your mobile device reports a screen/window size of 411 x 487 -a weird size- you might say, but that is in CSS pixel units, if we multiply those by the devicePixelRatio we get a size of 1078 x 1278 which tells us that most likely the device screen is actually a 1080 x 1280 screen, as originally advertised by your favorite phone manufacturer.
Now, to size stuff...
Say we want a canvas filling the whole screen. Set your CSS Size match the screen size (or any box size you want).
canvas.style.width = '411px';
canvas.style.height = '487px';
Now set the Canvas Size to the same but scaled-up by devicePixelRatio:
canvas.width = 411 * window.devicePixelRatio;
canvas.height = 487 * window.devicePixelRatio;
Now you can render your images.
When the browser calculates the layouts, it will have to scale-down your canvas to make it fit in its DOM rectangle area, the down-scale factor is cssSize / canvasSize yielding a down-scale factor of 1 / devicePixelRatio.
And then when the browser needs to render the layout to physical screen, it will scale it up by devicePixelRatio, thus leaving a total scaling of 1.0.
TL;DR
Supersampling. Scale up your canvas logical size by devicePixelRatio while keeping your CSS size at whatever size you need, and let the browser do the rest.
NOTE: If your rendering expects the canvas to be of certain size, and this "scaling up" messes up your layout and/or calculations, use the canvas setTransform method to scale down your "logical units" by 1.0 / devicePixelRatio, no quality is loss at all.
I have a monitor with 1920x1080 resolution for my laptop and a Surface Pro 3 with 1920x1280 resolution. I am developing a web page designed for full-screen viewing on 1920x1080 and 1920x1280 displays.
I have confirmed the settings for each display (see below).
Why am I getting 8xx instead of 1280? How can I obtain a value of 1280 to match the resolution height of the Surface Pro 3?
1920x1080 monitor (on Windows 8):
1920x1280 (Surface Pro 3) display (on Windows 10):
Using $(window).height() on my 1920x1080 monitor, I get the following:
That works for me.
However, using suggestions from this question for my 1920x1280 (Surface Pro 3) display...
Using suggestions from the accepted answer.
Using $(window).height():
Using $(document).height():
Using screen.height:
Using the suggestion from this answer:
Using the suggestion from this answer:
Using the suggestion from this answer:
Using the suggestion from this answer and this answer and this answer:
Using this suggestion from this answer:
This suggestion is a self-recommendation of a plugin. I will pass on this for now.
This suggestion uses a Coffee solution. I'll stick to JavaScript and jQuery for now.
Using this suggestion from this answer (which regurgitates a few other answers):
This suggestion requires an external library. I will pass on this for now.
Using the suggestion from this answer:
This suggestion was incorporated into a few other answers above.
It seems that your Surface Pro 3 uses an operating system wide zoom factor of 150%. Due to this the browser returns width 1280 and height 853 (as 1280 * 1.5 = 1920 and 853 * 1.5 = 1280). Switch Windows' zoom factor to 100% in Control Panel and your browser will return width and height as expected.
1) How can I obtain a value of 1280 to match the resolution height of the Surface Pro 3?
Have you tried
window.outerHeight
yet?
All I see in your test cases is the innerHeight.
That's only showing you what the browser will render(pixels will be zoomed, etc.. decreasing the available width you actually have)
2) Why am i getting 8xx instead of 1280?
Basically, browsers will zoom text/images/ etc.. to give a consistent experience across several resolutions.
Even though you are building it for a 1280 screen, you might only have 8xx pixels to your availability.
For more information about the pixeling I advice you read:
http://www.quirksmode.org/blog/archives/2010/04/a_pixel_is_not.html
Here is a solution that worked for me in Firefox, Chrome, IE11, and Edge. I don't have a Mac to test on but this should work there too. You need to factor in the device pixel ratio. Here is an example (JSBin):
var screenHeight = window.devicePixelRatio * screen.height;
This will give you the screen dimensions regardless of DPI of the device.
An important thing to note is that innerHeight (size of window without browser UI) and outerHeight (size of window with browser UI) are relative to the browser window. You should use those instead of screen.height if you want to know the size of the browser window.
In the browser, you deal with the abstraction of CSS pixels, not with physical pixels. The size reported to you is most likely correct (unless there is a weird browser bug at play), so the height of the window is 853 CSS pixels.
My advice would be to work with that size. Adjust your layout with media queries etc. Don't try to second-guess the browser; don't optimize for hardware specifics which browser vendors, and web standards, are actively trying to hide from you.
(I'll try to expand this answer later on, if I have the time. A proper explanation of the concepts is the length of a blog post.)
I am developing a web site and want see how it works on Google Pixel and Google Pixel XL devices. As I don't have the access to those devices, I need to know the view port width, height and device-pixel-ratio of those devices.
I have tried searching on Google but still couldn't find anything useful. Latest Chrome also doesn't list those devices' sizes in developer tools.
It will be really helpful if anyone have the access to these devices can figure the required information out.
Both the Pixel and Pixel XL are listed to have a css pixel resolution of 411×731, with device-pixel-ratios of 2.6 and 3.5 respectively.
Source: https://material.io/devices/ which is a Google site.
That's odd though, considering most phones get more effective pixels as the screen size increases, rather than just blowing everything up bigger and getting a higher dppx (Dots Per Pixel).
That does jive with Lord Flash's screen capture from the smaller Pixel; but doesn't help to validate the Pixel XL. If someone could post a screen capture from the Pixel XL I could determine the scaling from that.
The normal Pixel has a Resolution of 1080 x 1920 pixels (~441 ppi pixel density)
The Pixel XL has a resolution of: 1440 x 2560 pixels
Here is also a screenshot of the normal one. Feel free to measure whatever aspect you want:
do you have the google pixel in hand?
load the page with JS code
var viewport = {
width : $(window).width(),
height : $(window).height()
};
alert(viewport.height);
alert(viewport.width);