Адаптивность под экраны игры или приложения на HTML

html-apps-responsive

Вопросы адаптивности приложения или игры под различные размеры экранов это пожалуй одно из самых нелёгких задач в Web-девелопинге. Причиной этому являются разнообразные физические размеры экрана, PPI (Количество пикселей на дюйм), а также собственно разрешение в пикселях. При разработки приложения или игры на HTML для мобильных устройств - адаптивность превращается в сущий ад, поскольку там самоё пёстрое разнообразие экраном со своими свойствами.

Я столкнулся с необходимостью создания адаптивного интерфейса когда создавал приложения для Android на HTML+CSS+JS. Однако создание адаптивности для приложения и для Web-страницы это совсем разные вещи. Страница в интернете представляет собой в большинстве случае просто контент и суть адаптивности подстроить этот контент под ширину экрана, тем самым обеспечив наиболее приемлемый способ получения информации. Ну и в конце-то концов если конечному пользователю на мобилке показался шрифт маленьким - он запросто его увеличит щепоткой, ведь зум никто не отменял. Совсем иное дело делать веб-приложение. При построении адаптивности может много появиться подводных камней, ведь у нормально приложения зума в интерфейсе нет - нужно опираться на всё и следить чтобы на всех PPI, всех разрешениях, всех физических размерах всех экранов все элементы интерфейса отображались кликабельно, информация легко читалась и всё было хорошо. И вот как раз этому следовать очень и очень трудно. Об этом мы и собираемся поговорить.

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

Сразу замечу очень важный тезис: начинайте делать интерфейс для мобильного экрана и уж только потом представляйте как его пользовать на планшете. С маленького в большой можно в любой момент увеличить scale'ом сохраняя размеры элементов относительно друг друга. Да, будут приятные большие элементы управления это хорошо на самом деле. Намного хуже, когда приходиться делать из большого в маленькое. Вот тут-то и может взорваться голова. Просто всё уменьших как с предыдущим случаем уже не получиться ибо элементы интерфейса на маленьких (физические размеры) экранах будут крошечными. 

Немного теории 

Давайте немного определимся что такое пиксели под которые мы собираемся делать адаптивный интерфейс. Для начала стоит упомянуть о плотности пикселей.

Коэффициент плотности может быть получен и использован так:

JS: window.devicePixelRatio

CSS: <link rel="stylesheet" media="screen and (-webkit-device-pixel-ratio: 1.5)" href="/hdpi.css" />

Если число равно 1 - значит экран обычной плотности пикселей, 0.75 - низкой, 1.5 - повышенной, 2 - Retina.

Плотность пикселей как вы уже наверное догадались это количество пикселей на единицу физического расстояния. Измеряют в PPI, о котором речь шла ранее. PPI это Pixels per inch (Количество пикселей на дюйм).

Чтобы было понятней CSS-пиксели это не физические пиксели устройства, это абстрактные пиксели. Они нужны для того чтобы экран сам решал как ему нужно их отображать. Например так как Retina экраны имеют высокую плотность и коэффициент 2, то DIV 200x300 CSS пикселей будет располагаться на экране iPhone 4 как 400x600 физических пикселей.

Грубо говоря если у вас ширина экрана 480 пикселей (Как в инструкции написано), это ещё не значит что CSS будет думать что ваша ширина экрана 480 пикселей. Вовсе нет!

Итак, как же определить CSS ширину?

На IOS очень просто это сделать, достаточно вызвать Javascript'ом screen.width и это вернёт как раз CSS размеры, а не фактическое количество пикселей в ширине устройства.

На Android-устройствах к сожалению screen.width возвращает полную ширину экрана без PPI изменений. Поэтому приходиться пользовать другими способами.

Также можно применить странице:

<meta name="viewport" content="width=device-width">

А затем вызвать document.documentElement.clientWidth и в большинстве браузеров это будет CSS шириной.

Если вы разрабатываете игру на андроидовском webview и хотите чтобы содержимое страницы автоматически растягивалось на весь экран - применяйте:

webview.getSettings().setLoadWithOverviewMode(true);
webview.getSettings().setUseWideViewPort(true);

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

Как вы сами наверное догадались сам мета viewport устанавливает браузеру количество CSS пикселей по высоте и ширине. Можно ширине установить 320px и будет 320px, даже если количество пикселей по ширине у вашего устройства 1080. Но будет 320 по ширине и если посчитать, то 1 CSS пиксель в данном случае будет порядка 3x3 физических пикселей устройства. С таким подходом будет здорово делать элементы интерфейса, но вот только дело дойдёт до картинок и вы поймёте что нужно использовать фулл сайз физических пикселей устройства, иначе будет немного низкого качества результат.

Для устройств на OS Android и Windows Phone CSS ширину можно найти поделив значение что вернёт screen.width на devicePixelRatio.

На IOS умножение devicePixelRatio на screen.width будет равно количеству физических пикселей в ширине экрана.

Рекомендую проверить экран таким тестом.

Однако знайте что у разных браузеров значения devicePixelRatio могут быть разными на одном экране. Например взять Galaxy Nexus (720x1280), где команда WebKit дала устройству devicePixelRatio равный 2 (720/360), а выходцы из Опера определили его как 2.25 (720/320).

Если вы хотите знать какие JS вызовы длинны и ширины в каких устройствах и браузерах работают, тогда посетите эту страницу.

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

Классическая адаптивность

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

1. Просто использовать CSS Медиа запросы

О CSS Media запросах мы уже писали статью, и вот основываясь на использование этих запросов можно сделать адаптивность.

Адаптивность вряд ли получиться хорошей, не для всего. Если у вас страница с контентом, с рассказом о том как Вася провёл лето - это будет нормал, но если у вас ИГРА на HTML+CSS+JS, то тут уже придётся попотеть. Однако игры делаются обычно в canvas или svg, там у них свой собственный scale, который можно крутить и всё общий размер будет меняться сохраняя при этом относительные размер элементов, но об этом дальше.

Если вы хотите именно с помощью медиа запросов делать оформление приложению для мобильных устройств, то вам потребудется таблица размеров вьюпорта, для того чтобы знать под какие разрешения делать медиа запросы. Грубо говоря ширина портретного вьюпорта обычно 320, 360, 384, 400, 480, 496, 533, 540, 600, 640, 648, 758, 768, 800, 1024.

Не забывайте что вы можете не только использовать пиксели, проценты в позиционировании, но также миллиметры (mm), сантиметры (cm) и дюймы (in). Очень часто это может помочь.

Использование Flexible CSS

Для построения адаптивности, также отлично может подойти использование Flexbox CSS, с помощью которого средствами CSS3 можно настроить поведение элементов относительно свойств других элементов. Рекомендуем погуглить Flexbox CSS, если вы не знаете что это такое.

Масштабное увеличение/уменьшение

Здесь я вам поведаю несколько способов адаптирования, при которых на всех экранах все элементы будут располагаться одинаково относительно друг друга, только их размер будет меняться в зависимости от размера экрана.

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

Использовать SVG

Если ваша игра простая, то вы можете использовать SVG для её отображения. Несмотря на то что на Андроид не поддерживается анимация SVG, адаптивность остаётся адаптивностью, а анимационные трюки можно выполнить и в CSS. Для адаптивности просто указывайте ширину/высоту (Можно высчитать javascript'том) и выставьте атрибут viewBox=”0 0 400 400″, где эти четыре числа замените на свои.

Использовать Canvas

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

В Canvas'е также можно увеличивать и уменьшать игровое поле в зависимости от размера устройства, но его нужно будет считать самим и адаптировать под канвас. Применять следует методом:

ctx=document.getElementById("canvas").getContext("2d");
ctx.scale(1,1);

Меняя цифры где 1,1 вы можете менять размер содержимого вьюпорта.

CSS+JS трюки

1. Сперва начнём с одного приёма на JS+CSS, при котором добывается масштабная адаптивность. Суть в том что при любом размере экрана размеры элементов относительно друг друга меняться не будут и всё будет растянуто как надо.

Пример (JSFiddle)

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

2. Вот пример того же только основную роль здесь играет CSS свойство -webkit-transform: scale(x,y):

Пример (JSFiddle)

О самом свойстве немного ниже вы прочитаете подробнее.

3. CSS Масштабирование

-webkit-transform: scale(x,y)

Буквально в нескольких словах опишу действие свойства. Данное CSS свойство способно увеличивать и уменьшать HTML элементы. При уменьшении и увеличении сохраняется центр объекта (т.е. он не смещается как если бы вы уменьшали высоту и ширину) и все вложенные в элемент дочерние HTML элементы также подвергнуться масштабированию.

Как вы уже поняли в scale(x,y), вместо x и y вы ставите число во сколько раз вы уменьшаете/увеличиваете содержимое элемента. Например scale(2,1) означает что вы растяните объект по x-оси и не будете масштабировать по y-оси. Если вы хотите изменять размеры объекта не меняя пропорций, вы можете использовать лишь одно число. Например, scale(3).

Это всё увеличение объектов с помощью свойства scale(). Если же вы хотите уменьшить объект, тогда ставите значения меньше единицы. Например, scale(0.5). Можно также инвертировать оси и для этого в свойстве нужно использовать отрицательные числа.

Плюсом такого масштабирования является прежде всего сохранение размеров дочерних объектов (относительно друг друга) элемента к которому применено свойство.

 

Адаптивный шрифт

Мало кто знает, но помимо использования классических CSS Media Queries, шрифт может автоматически масштабироваться несколькими путями:

1. Использование единицы измерения vw, vh, vmin, vmax. Например:

font-size:4vw;

Очень немногие знают о том что такое существует в CSS и довольно большое количество браузеров это поддерживают (на некоторых браузерах просто нет поддержки real-time изменения когда вы меняете размер страницы, но оно и не нужно).

Единица измерения vw полностью зависит от ширины браузера (физической ширины), а соответственно также от ширины элемента куда помещён. И установив значения единожды, вы можете быть уверены, что ваш текст будет также отображаться в относительном плане к ширине любого экрана.

Для того чтобы вы лучше понимали что это. 1 vw=1% физической ширины браузера.

Тоже самое можно сказать о vh, только это затрагивает высоты вьюпорта, а не ширину. Отсюда и пошло название vw (View Width) vh (View Height). Соответственно 1 vh= 1% высоты браузера.

1 vmin - 1vw или 1vh (Выбирается тот который физически меньше)

1 vmax - 1vw или 1vh (Выбирается тот который физически больше)

2. Очень полезно иногда использовать для шрифта mm и cm. Таким образом вы не зависите ни от разрешения экрана ни от плотности пикселей и можете спокойно быть уверенными что ваш текст отобразиться примерно одинакового размера на всех типах устройств. Не забывайте об этом!

3. Можно использовать проценты для шрифта (%). Но тут есть один небольшой ньюанс. 100% не значит растянуть шрифт на 100% ширины, высоты или что-то в этом духе. 100% означает использовать точный размер родительского размера шрифта. Что бы понять это масло масляное покажу пример:

body{
font-size:16px;
}
.upblock{
font-size:150%;
}
.footer{
font-size:50%;
}

Из примера выйдет что к тексту с классом footer примениться размер равный 8px, а к upblock - 24px.

Плюс данного подхода в том что вы можете изменять в зависимости от размера экрана/плотности пикселей только одну величину - родительский размер шрифта, сохраняя при этом размеры шрифта элементов относительно друг друга.

По такому же принципу работает и единица измерения em. Выделяться под неё отдельный пункт не будет поскольку принцип работы тот же самый. 

Что вам ещё стоит запомнить из этого пункта, так это то что вы можете задавать родительский размер шрифта также в процентах или в em при чём тогда, 1em = 16px = 100%.

Есть также rem - единица измерения шрифта. Отличается от em тем что наследуется не от родительского элемента, а от того размера шрифта который был указан в html{}.

Не забывайте что вы также можете воздействовать на размер шрифта применяя к целому блоку -webkit-transform: scale(x,y), о котором подробнее говорило выше на странице.

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

Если вы знаете чем дополнить материал, обязательно пишите свои мысли в комментарии и прикладывайте рабочий пример в JSFiddle.


You have no rights to post comments

Карта сайта