Получение физических размеров экрана / точек на дюйм / плотности пикселей в Chrome на Android

Вопрос

Есть ли безопасный способ получить действительно правильные физические размеры экрана в Chrome на Android? При необходимости старые версии Chrome и Android могут быть оставлены вне поля зрения.

Предыдущие исследования

Существует множество тупиковых вопросов о стековом потоке о получении реальных физических размеров экрана устройства из javascript (или css). Кажется, что нет никакой конвергенции между стандартизацией html api и фактическими реализациями браузера в этом, не говоря уже о том, что реализация браузера основана на OS API, которые, в свою очередь, полагаются на аппаратное обеспечение, предоставляющее правильную информацию.

Между прочим, некоторые предыдущие ответы являются загадочными (год 2011 и т. П.), Предполагая определенную плотность пикселей, которая преобладала в то время и поэтому бесполезна. Другие относятся к webkit, в то время как Chrome blink, возможно, заменил webkit в chrome (?).

Я хотел бы изучить существование простого решения, ограничивающего только Chrome на Android.

Заметка

Это все о решении javascript (или css) внутри браузера, а не о решении для нативного приложения.

14 ответов

Вы не можете реально получить реальные физические размеры или фактическое DPI, и даже если вы можете, вы ничего не можете с ними сделать.

Это довольно длинная и сложная история, так что прости меня.

Интернет и все браузеры определяют 1px как единицу, называемую пикселем CSS. Пиксель CSS - это не реальный пиксель, а единица, которая считается 1/96 дюйма в зависимости от угла обзора устройства. Это указывается как опорный пиксель.

Опорный пиксель - это угол обзора одного пикселя на устройстве с плотностью пикселей 96 точек на дюйм и расстоянием от считывающего устройства до длины руки. Поэтому для номинальной длины руки в 28 дюймов угол обзора составляет около 0,0213 градусов. Таким образом, для чтения на расстоянии вытянутой руки 1 пиксель соответствует примерно 0,26 мм (1/96 дюйма).

В 0,26 мм пространства у нас может быть очень много пикселей реального устройства.

Браузер делает это в основном по унаследованным причинам - большинство мониторов имели 96dpi при рождении в Интернете - но также и для согласованности, в "старые времена" кнопка 22px на 15-дюймовом экране с разрешением 800x600 была бы в два раза больше кнопки 22px на 15-дюймовый монитор с разрешением 1600x1200. В этом случае DPI экрана фактически в 2 раза (вдвое больше разрешения по горизонтали, но в том же физическом пространстве). Это плохая ситуация для Интернета и приложений, поэтому большинство операционных систем разработали множество способов абстрагирования значений пикселей в независимые от устройства единицы (DIPS на Android, PT на iOS и CSS Pixel в Интернете).

Браузер iPhone Safari был первым (насколько мне известно), представившим концепцию области просмотра. Это было создано, чтобы позволить приложениям в стиле рабочего стола полностью отображаться на маленьком экране. Область просмотра была определена как 960px в ширину. Это по сути увеличило страницу в 3 раза (iphone изначально был 320px), поэтому 1 пиксель CSS составляет 1/3 физического пикселя. Когда вы определили область просмотра, вы можете получить это устройство, чтобы оно соответствовало 1 пикселю CSS = 1 реальному пикселю при 163 точек на дюйм.

Использование области просмотра, где ширина равна "ширине устройства", освобождает вас от необходимости устанавливать ширину области просмотра для каждого устройства на оптимальный размер CSS-пикселя, браузер просто делает это за вас.

С появлением устройств с двойным разрешением, производители мобильных телефонов не хотели, чтобы мобильные страницы казались на 50% меньше, поэтому они представили концепцию, называемую devicePixelRatio (я думаю, что она впервые появилась в мобильном веб-наборе), что позволяет им сохранять 1 пиксель CSS примерно равным 1 96 дюймов, но вы должны понимать, что ваши активы, такие как изображения, могут быть в два раза больше. Если вы посмотрите на серию iPhone, все их устройства говорят, что ширина экрана в пикселях CSS составляет 320 пикселей, хотя мы знаем, что это не так.

Поэтому, если вы сделали кнопку размером 22 пикселя в пространстве CSS, представление на физическом экране будет иметь соотношение пикселей устройства * 22 *. На самом деле я говорю это, это не совсем так, потому что соотношение пикселей устройства также никогда не бывает точным, производители телефонов установили для него хорошее число, например 2.0, 3.0, а не 2.1329857289918....

Таким образом, CSS-пиксели не зависят от устройства, и нам не нужно беспокоиться о физических размерах экранов, плотности отображения и т. Д.

Мораль этой истории такова: не беспокойтесь о понимании физического размера пикселя экрана. Тебе это не нужно. 50px должен выглядеть примерно одинаково на всех мобильных устройствах, он может немного отличаться, но CSS Pixel - это независимый от нашего устройства способ создания согласованных документов и интерфейсов пользователя.

Ресурсы:

Основываясь на ответе Мэтта, я сделал тест:

// on Macbook Pro Retina (2880x1800, 15.4"), is the calculated diagonal size
// approximately 15.4? Let's see...

var svgEl = document.createElementNS("http://www.w3.org/2000/svg", "svg");
var screenWidthMillimeters = svgEl.screenPixelToMillimeterX * 2880;
var screenHeightMillimeters = svgEl.screenPixelToMillimeterY * 1800;
var screenDiagonalMillimeters = Math.sqrt(Math.pow(screenWidthMillimeters, 2) + Math.pow(screenHeightMillimeters, 2)); // pythagorean theorem
var screenDiagonalInches = (screenDiagonalMillimeters / 10 / 2.54); // (mm / 10mm/cm) / 2.54cm/in = in

console.log("The calculated diagonal of the screen is "+screenDiagonalInches+" inches. \nIs that close to the actual 15.4\"?");

Это вывод:

The calculated diagonal of the screen is 35.37742738560738 inches. 
Is that close to the actual value of 15.4?

Нету.

Так что, похоже, пока нет способа получить реальные физические значения в веб-браузере.

Вы можете создать любой элемент страницы и установить его ширину, используя реальные физические единицы. Например

<div id="meter" style="width:10cm"></div>

А затем получить его ширину в пикселях. Например, HTML-код ниже (я использовал JQuery) показывает ширину экрана устройства в сантиметрах

<script>
var pixPer10CM = $('#meter').width();
var CMPerPix = 10 / pixPer10CM;
var widthCM = screen.width * CMPerPix;

alert(widthCM);
</script>

В качестве дополнения к ответу "нет хорошего решения этой проблемы", просто отметьте единицы, которые вы можете использовать в CSS https://www.w3schools.com/cssref/css_units.asp

Unit    Description
cm      centimeters
mm      millimeters
in      inches (1in = 96px = 2.54cm)
px *    pixels (1px = 1/96th of 1in)
pt      points (1pt = 1/72 of 1in)
pc      picas (1pc = 12 pt)

* Pixels (px) are relative to the viewing device.
For low-dpi devices, 1px is one device pixel (dot) of the display.
For printers and high resolution screens 1px implies multiple device pixels.

С этим описанием кажется, что есть решение. cm, mm а также in будет использоваться для рисования чего-либо с одинаковым размером независимо от размера экрана и разрешения. Имея это в виду, вы можете ожидать, что по крайней мере один из px, pt или же pc может использоваться для рисования на уровне пикселей с любой точностью, которую вы хотели бы использовать (в противном случае, какой смысл иметь миллионы пикселей, верно?). Ну нет. Все единицы являются долями метрической единицы, что делает все эти единицы просто разными масштабами. И худшим в этой истории является тот факт, что ни один из них не является точным. Просто поиграйте с примером w3schools (нарисуйте линию длиной 20 см и измерьте ее линейкой).

Итак, в конце концов: - нет возможности точно нарисовать что-то с физическими размерами (что должно быть в случае с cm, mm, inи в конце концов pt а также pc). - невозможно нарисовать что-либо с одинаковым размером независимо от размера и разрешения экрана (что должно быть в случае, по крайней мере, px).

Это как проблема реализации (фактический размер экрана не используется), так и проблема дизайна (почему px быть независимым от размера экрана, в то время как для этого уже есть много единиц).

Вы можете получить эту информацию с WURFL:

Свойства отображения устройства

Атрибуты называются:

resolution_(width|height)

physical_display_(width|height)

Длинная версия:

Лучшая и наиболее надежная стратегия для достижения этой цели - отправить user agent string из браузера в БД вроде WURFL (или другое) актуальная БД, которая может предоставить необходимую информацию.

Строка агента пользователя

Это часть информации, которую могут предоставить все современные браузеры; он предоставляет информацию об устройстве и его ОС. Это просто не достаточно значимо для вашего приложения без помощи словаря, как WURFL,

WURFL

Эта база данных обычно используется для определения свойств устройства.

С его помощью вы сможете точно поддерживать большинство популярных устройств на рынке. Я хотел бы опубликовать демонстрационный код, но один доступен с загрузкой на WURFL сайт. Вы можете найти такую ​​демонстрацию в папке examples/demo, которая загружается вместе с библиотекой.

Скачать WURFL

Вот дополнительная информация и объяснение о проверке физического размера и разрешения: http://www.scientiamobile.com/forum/viewtopic.php?f=16&t=286

В ответ на ответ zehelvion об использовании WURFL для поиска разрешения также стоит упомянуть, что WURFL также доступен в виде фрагмента JavaScript.

В бесплатной версии, предлагаемой на http://wurfl.io/, вы не получите информацию об экране и разрешении (только имя устройства, форм-фактор и мобильный / не мобильный), но есть и коммерческая версия с более широкими возможностями.

CSS-пиксели на самом деле не являются нашим "независимым от устройства пикселем". Веб-платформа состоит из множества типов устройств. В то время как пиксель CSS на портативных устройствах выглядит довольно согласованно, на обычном настольном мониторе с разрешением 96 dpi он будет на 50% больше. Смотри мой вопрос. В некоторых случаях это действительно неплохо, например, шрифты должны быть больше на большом экране, так как расстояние до глаза больше. Но размеры элементов пользовательского интерфейса должны быть достаточно согласованными. Допустим, у вашего приложения есть верхняя полоса, вы бы предпочли, чтобы она была одинаковой толщины на настольных и мобильных устройствах, по умолчанию она будет на 50% меньше, что нехорошо, поскольку сенсорные элементы должны быть больше. Единственный обходной путь, который я нашел, - это применение разных стилей в зависимости от DPI устройства.

Вы можете получить разрешение экрана в JavaScript с помощью window.devicePixelRatio . Или CSS-запрос:

@media  only screen and (-webkit-min-device-pixel-ratio: 1.3),
    only screen and (-o-min-device-pixel-ratio: 13/10),
    only screen and (min-resolution: 120dpi)
    {
     /* specific styles for handhelds/ high dpi monitors*/
    }

Я не знаю, как применить это на настольном мониторе с высоким разрешением. Возможно, элементы будут слишком маленькими. Очень жаль, что веб-платформа не предлагает ничего лучшего. Я думаю, что реализация dip не будет слишком сложной.

Я решил эту проблему с помощью одного из своих веб-проектов http://www.vinodiscover.com/. Ответ таков: вы не можете точно знать, каков физический размер, но вы можете получить приблизительное значение. Используя JS и / или CSS, вы можете найти ширину и высоту области просмотра / экрана, а также плотность пикселей с помощью медиа-запросов. Например: iPhone 5 (326 пикселей на дюйм) = 320 пикселей на 568 пикселей и плотность пикселей 2,0, а Samsung Galaxy S4 (441 пикселей на дюйм) = 360 пикселей x 640 пикселей и плотность пикселей 3,0. Фактически плотность пикселей 1,0 составляет около 150 пикселей на дюйм.

Учитывая это, я установил свой CSS, чтобы показывать 1 столбец, когда ширина меньше 284 пикселей, независимо от плотности пикселей; затем два столбца от 284 до 568 пикселей; затем 3 столбца выше 852px. Это намного проще, чем кажется, так как браузеры теперь выполняют вычисления плотности пикселей автоматически.

http://www.quirksmode.org/blog/archives/2010/04/a_pixel_is_not.html

Используя функцию getPPI() ( мобильная сеть: как получить физический размер в пикселях?), Для получения идентификатора в один дюйм используйте следующую формулу:

var ppi = getPPI();
var x   = ppi * devicePixelRatio * screen.pixelDepth / 24;
$('#Cubo').width (x);
$('#Cubo').height(x);

<div id="Cubo" style="background-color:red;"></div>

Я заметил в ваших комментариях, что вы на самом деле были обеспокоены размером, который кнопки и т. Д. Показывают зрителю.

У меня была такая же проблема, пока я не обнаружил, что это просто вопрос добавления метатега в заголовок HTML для установки начального масштаба:

<meta name="viewport" content="width=device-width, initial-scale=1">

Я работал над ответом на этот вопрос в течение довольно долгого времени, и, похоже, есть способ получить размер экрана в дюймах практически для всех устройств без таблиц поиска и тому подобного.

В настоящее время я приближаюсь к концу бета-тестирования с хорошими результатами (код запутан и домен заблокирован, пока я не узнаю, что он работает как задумано).

Я тестировал свое решение здесь: this.Device, и любые отзывы будут очень кстати. Это чисто математическое решение, и оно может работать в автономном режиме, поскольку БД не требуется.

Мне было бы интересно услышать, работает ли это для вас.

JqueryMobile ширина элемента

$(window).width();   // returns width of browser viewport
$(document).width(); // returns width of HTML document

JqueryMobile Высота элемента

$(window).height();   // returns height of browser viewport
$(document).height(); // returns height of HTML document

Удачи Дэнни117

Хех, хотел бы я ответить на этот вопрос, но фанаты, создающие API-интерфейсы, не предоставляют базовых вещей и временами слишком абстрагируются.

Кстати, у меня есть 40-летний опыт проектирования пользовательского интерфейса и программного обеспечения, и я настаивал на том, чтобы иметь это, что кажется вечным, еще до тех пор, пока не появились драйверы "VESA":).

Для сенсорного экрана у меня была вещь, которую я назвал "fingerSize()", которая представляла собой количество пикселей, равное 1 см (очень близко к диаметру средней области касания пальца), но исходные данные - "dpcm".

Еще одна вещь, которую вы хотите от дисплея, - это "угол обзора". Тип устройства отображения для просмотра и сенсорная функция в значительной степени определяют расстояние просмотра.

    (Not code but I wanted fixed width font)

    Hand held - Phone/Tablet         25cm 
    Touch screen / Desktop Monitor   40cm         ( seated or standing at a counter
                                                    with partially extended arm )
    "Personal" Touch kiosk        50cm -> 80cm ( a bit further away standing 
                                                 extended arms and standing back 
                                                 to view )
    Presentation Screen.          any distance ( angle of view derived from pixel
                                                 width of device. An ideal conventional cinema 
                                                 seat (as opposed to imax or immersive) 
                                                 you want about 50 degrees
                                                 between edges of the screen. from viewer POV )

    So what you want universally available is:

    device usage type.
    finger size in pixels (dots per CM)
    pixel dimensions of display.

    Then internally, when laying out and drawing you want the size/shape of a pixel 
    for the current transform. 

Это то, что мы стараемся предоставить в наших API, но, увы, во многих случаях это трудно получить.

Вы можете получить приблизительную оценку размера, но она не точна.

Я собрал пример, который я протестировал на нескольких устройствах, чтобы увидеть, каковы были результаты. Мой iPhone 6 возвращает значения примерно на 33% больше. Мой 27-дюймовый настольный монитор на моем Mac был представлен как 30-дюймовый монитор.

var $el = document.createElement('div');
$el.style.width = '1cm';
$el.style.height = '1cm';
$el.style.backgroundColor = '#ff0000';
$el.style.position = 'fixed';
$el.style.bottom = 0;
document.body.appendChild($el);
var screenDiagonal = Math.sqrt(Math.pow((window.screen.width / $el.offsetWidth), 2) + Math.pow((window.screen.height / $el.offsetHeight), 2));
var screenDiagonalInches = (screenDiagonal / 2.54);
var str = [
  '1cm (W): ' + $el.offsetWidth + 'px',
  '1cm (H): ' + $el.offsetHeight + 'px',
  'Screen width: ' + window.screen.width + 'px',
  'Screen height: ' + window.screen.height + 'px',
  'Browser width: ' + window.innerWidth + 'px',
  'Browser height: ' + window.innerHeight + 'px',
  'Screen available width: ' + window.screen.availWidth + 'px',
  'Screen available height: ' + window.screen.availHeight + 'px',
  'Screen width: ' + (window.screen.width / $el.offsetWidth).toFixed(2) + 'cm',
  'Screen height: ' + (window.screen.height / $el.offsetHeight).toFixed(2) + 'cm',
  'Screen diagonal: ' + screenDiagonal.toFixed(2) + 'cm',
  'Screen diagonal: ' + screenDiagonalInches.toFixed(2) + 'in',
  'Device Pixel Ratio: ' + (window.devicePixelRatio || 1)
].join('\n');
var $pre = document.createElement('pre');
$pre.innerHTML = str;
document.body.appendChild($pre);

http://codepen.io/kus/full/xOAPYB/

Другие вопросы по тегам