* Не привлекая внимания санитаров
Меня зовут Илья, я занимаюсь фронтенд‑разработкой вот уже 10 лет. Представьте, что вам нужно сделать стили для печати документов, а бегать к принтеру с линейкой, чтобы убедиться в корректности фактических размеров отдельных элементов, очень не хочется. Было бы куда проще иметь возможность приложить ту же линейку к экрану. Но размеры элементов на экране почти всегда не соответствуют их физическим размерам при печати. Казалось бы, зачем это вообще может быть кому‑то нужно. Но это бывает важно. Например, в типографиях.
Как вы уже догадались, работаю я не в типографии, поэтому с подобной проблемой не сталкивался. Но в свободное время интересуюсь необычными задачами из мира веб‑разработки, так сказать, расширяю кругозор. И вот однажды я услышал тезис, что добиться точного воспроизведения реальных размеров на экране невозможно.
Что ж, вызов был брошен. И я поставил себе задачу (вы же тоже сами ставите себе задачи?) — нарисовать красивый красный квадратик размером 3 × 3 см. Тому, что у меня в итоге получилось, и посвящён мой необычный рассказ.
Подготовка
План простой. Верстаю красивый красный квадратик размером 3 × 3 см. Собираю по квартире ПЭВМ разных классов и размеров. Привожу их в порядок. Беру метр и начинаю измерения.
Решение в лоб
Код квадрата достаточно прост:
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <title></title> <link rel="icon" href="data:image/png;base64,"> <style> *, :before, :after { box-sizing: border-box; } html, body { width: 100vw; height: 100vh; margin: 0; } body { display: flex; flex-direction: column; justify-content: center; align-items: center; } .square { width: 3cm; height: 3cm; background: red; } </style> </head> <body> <div class="square"></div> </body> </html>
Можете сами взять в руки линейку и замерить, что у вас получилось.
Красивый красный квадратик свёрстан. Отцентрирован. Размещён на сервере и измерен почти на всём, что я нашёл в закромах. Хорошая новость — красивый красный квадратик отображается на всех шайтан‑машинах, плохая — он ни разу не 3 × 3 см.
Результаты
Таблица устройств и их характеристик с результатами измерений:
Ну и фото, чтобы оценить масштабы катастрофы. Разброд и шатание. Задача не решена.
Дело в том, что 1 дюйм = 2,54 см = 96 пикселей. Всё. Это не зависит от устройства. Одним словом, в CSS нет абсолютных единиц измерения, а только относительные (не берём стили для печати). Не буду растекаться мыслью по древу, вот статья, где об этом написано подробнее, и спецификация.
Решение на основе диагонали экрана
Вы знаете размеры экрана устройства, с которого вы читаете данное безобразие? Ширину и высоту — почти уверен, что нет, а диагональ — скорее всего, да (или можете легко узнать). Для массовых железяк диагональ указана в характеристиках. Я так её и нашёл для своего зоопарка.
Допустим, диагональ мы знаем: нашли, заняли, украли, узнали от окружения (приложение для телевизора или смартфона), получили с сервера, она прилетела из космоса или её ввёл пользователь.
Диагональ — это гипотенуза прямоугольного треугольника. Соотношение сторон берём из разрешения из window.screen
(window.screen.width
и window.screen.height
). Зная гипотенузу и соотношение катетов из формулы теоремы Пифагора , после нехитрых преобразований получаем такую формулу:
где — ширина, — высота, — диагональ, — соотношение ширины и высоты.
Далее берём ширину и делим на window.screen.width. И получаем количество пикселей на физический дюйм. Я буду работать с сантиметрами.
Его величество код
<!doctype html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0"> <title></title> <link rel="icon" href="data:image/png;base64,"> <style> *, :before, :after { box-sizing: border-box; } :root { --pixes-per-cm: 0; } html, body { width: 100vw; height: 100vh; margin: 0; } body { display: flex; flex-direction: column; justify-content: center; align-items: center; } .square { width: clamp(3px, calc(3 * var(--pixes-per-cm)), 100%); height: clamp(3px, calc(3 * var(--pixes-per-cm)), 100%); background: red; } input { width: 3cm; margin-top: 20px; } .panel { position: fixed; top: 0; left: 0; } </style> </head> <body> <div class="panel"> <p>Разрешение: <b class="resolution"></b></p> <p>Физические размеры: <b class="sizes"></b></p> <p>Пикселей/см: <b class="pxs-per-cm"></b></p> </div> <div class="square"></div> <input type="text" value=""> <script> function setValue(selector, value) { if (document.querySelector(selector)) { document.querySelector(selector).textContent = value } } function render() { const value = document.querySelector('input')?.value const d = (Number(value) || 0) * 2.54 const { width, height } = screen const sidesRatio = width / height const physicalWidth = Math.sqrt(d ** 2 / (1 + sidesRatio ** 2)) * sidesRatio const physicalHeight = Math.sqrt(d ** 2 / (1 + sidesRatio ** 2)) let pixelsPerCm = height / physicalHeight if (pixelsPerCm === Infinity) { pixelsPerCm = 0 } document.body.style.setProperty('--pixes-per-cm', `${pixelsPerCm}px`) setValue('.resolution', `${screen.width}x${screen.height}`) setValue('.sizes', `${physicalWidth.toFixed(2)} см x ${physicalHeight.toFixed(2)} см`) setValue('.pxs-per-cm', pixelsPerCm.toFixed(2)) } setInterval(render, 200) </script> </body> </html>
Не стесняемся. Открываем страницу, вводим диагональ и замеряем красивый красный квадратик линейкой.
Ну и я замерю. Прекрасные фото красивого красного квадратика 3 × 3 см. Мечта. Фото с моего зоопарка прилагаю:
Я сделаль!
Получил свой желанный красивый красный квадратик с заданными характеристиками. Пусть и с большой оговоркой, но задачу я решил.
Отдельно скажу про два последних скрина. На первом — Firefox без зума, а на втором — Firefox с зумом 110% (мне так удобнее) отсюда и изменение разрешения. Тем не менее красивый красный квадратик как был 3 × 3 см, так и остался. Ширина поля ввода — 3 виртуальных сантиметра, и его размер «плавает» от устройства к устройству.
Теперь вы знаете, что можно подружить физические и виртуальные сантиметры. Может, это даже вам пригодится. Если вы сталкивались с подобной задачей или знаете, где можно применить данное нетайное знание, пишите в комментариях.
ссылка на оригинал статьи https://habr.com/ru/articles/847000/
Добавить комментарий