Введение в разработку приложений для Windows 8 с использованием HTML, CSS и JavaScript

Макет

Разбить на страницы
Показывать лекцию целиком

Файлы к данной лекции Вы можете скачать здесь.

В сравнении с другими членами моей семьи, я меньше сплю и часто встаю поздно ночью или перед рассветом. Для того, чтобы не будить остальных, я обычно не включаю свет и перемещаюсь в темноте (здесь, в сельских предгорьях Сьерра-Невады, бывает по-настоящему темно!) Так как я знаю планировку дома и расстановку мебели, мне не нужно многого видеть. Я лишь нуждаюсь в нескольких контрольных точках, вроде дверного проёма, углов стен или края кровати, для того, чтобы точно знать, где я нахожусь. Более того, моё тело обладает мышечной памятью, в которой зафиксировано расположение дверных ручек, количество ступенек на лестнице, количество шагов, необходимое, чтобы обойти кровать и так далее. Это по-настоящему помогло мне понять, как слабовидящие люди "видят" их мир.

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

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

Хороший дизайн приложения, очевидно, следует тем же принципам. Именно поэтому Microsoft рекомендует следовать единообразным шаблонам поведения приложений, как описано в материалах "Разработка интерфейсов пользователя для приложений" (лекции 1 курса "Пользовательский интерфейс приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript"), продиктованы особенностями анатомии людей, а именно, тому, как далеко мы можем перемещать пальцы по экрану, удерживая при этом в руках планшетный компьютер.

В случае с макетами страниц, рекомендации, "Создание макета приложения" (http://msdn.microsoft.com/library/windows/apps/hh872191.aspx), где показано идеальное расположение тела страницы и заголовков, где выверены расстояния между элементами страницы, могут показаться серьезно ограничивающими ваши возможности, если не драконовскими. Общий стиль Windows, однако - это отличная отправная точка, но не жёсткое правило. Гораздо важнее, что форма макета приложения помогает пользователям развивать визуальную и мышечную память, которая применима ко многим приложениям. Исследования показали, что пользователь вырабатывает подобные привычки довольно быстро, за минуты. Но, конечно, эти привычки не имеют попиксельной точности. Другими словами, общий стиль показывает общую форму, которая помогает пользователю немедленно понять, как работает приложение и где нужно искать определенные его функции. Это похоже на то, как вы легко узнаете букву "S", набранную разными шрифтами. Такой подход эффективен и продуктивен. С другой стороны, когда существует приложение, которые использует совершенно иной макет (или, что хуже, когда макет похож на макет в стиле Windows 8, а работает он иначе), пользователь может потратить больше сил на то, чтобы понять, куда посмотреть, куда кликнуть, так же, как я вынужден был бы быть гораздо более внимательным ночью, если бы вы передвинули всю мою мебель!

Суть заключается в том, что за всеми рекомендациями по проектированию приложений для Магазина Windows лежат веские причины. Как я сказал раньше, если вы выполняете роль дизайнера своего приложения, изучите те руководства, ссылки на которые приведены выше. Если эту роль взял на себя кто-то другой, убедитесь в том, что он изучил эти руководства! В любом случае, мы рассмотрим основные принципы в первом разделе данной лекции.

После этого мы скоцентрируемся на том, как реализовать дизайн макета, а не на создании дизайна как такового. (Хотя я, очевидно, унаследовал от моих родителей гены, которые наградили меня способностями к технической коммуникации, мой брат получил больше генов, которые в ответе за искусство!). Например, мы ответим на вопросы о том, как приложение должно отвечать на изменение режима просмотра для того, чтобы показать страницы в правильном дизайне (для полноэкранного альбомного, заполняющего, прикрепленного, портретного режимов)? Как приложение ведет себя на экранах различных размеров и различной плотности пикселей?

Кроме того, мы потратим некоторое время на работу с CSS-сеткой и некоторыми другими возможностями CSS, имеющими отношение к макетам, такими, как гибкие окна или многоколоночный текст. Вообще говоря, всё это - стандарты CSS, поэтому я ожидаю, что вы уже знаете что-то о них, или можете разыскать полную документацию по нимТехническую документацию можно найти по адресу: http://www.w3c.org; а именно, начните с http://www.w3.org/standards/webdesign/htmlcss и для HTML и для CSS. Кроме того, я горячо рекомендую отлично спроектированные и находящиеся под наблюдением ресурсы из Smashing Magazine для изучения нюансов CSS, которые, должен признать, время от времени кажутся мне весьма таинственными.. Мы, таким образом, рассмотрим лишь некоторые основы, потратив больше времени на то, чтобы понять, как лучше всего применять эти возможности в приложениях, и на аспекты, уникальные для среды Windows 8 (на то, например, что называется точкой прикрепления (snap point) в элементе div, поддерживающем сдвиг / прокрутку (pan / scroll)).

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

Принципы построения макетов приложений для Магазина Windows

Макет, очевидно, является одним из центральных элементов, которого касаются рекомендации по дизайну приложений для Windows. Принцип "прежде всего содержимое, и лишь затем внешнее оформление" ("content before chrome") означает, что большая часть того, что вы отображаете на каждой из страниц приложения - это содержимое, с небольшим количеством управляющих поверхностей, постоянных навигационных панелей и пассивных графических элементов наподобие разделителей, размытий, градиентов, которые сами по себе ничего не значат. Другой вариант реализации подобного заключается в том, что содержимое само по себе следует сделать интерактивным, вместо того, чтобы конструкировать пассивные элементы, управляющее воздействие на которые оказывают команды, активируемые пользователем не посредством самих этих элементов. Семантическое масштабирование - хороший пример подобного интерактивного содержимого - вместо необходимости иметь кнопки или меню для изменения масштаба где-то в приложении, эту возможность реализует сам элемент управления, иногда, когда с приложением работают с помощью мыши, выводя небольшую кнопку зуммирования. Другие команды приложения, по большей части, похожим образом привязаны к элементам пользовательского интерфейса, которые появляются тогда, когда они нужны, посредством панелей приложения и других всплывающих элементов, о которых мы поговорим в лекции 1 курса "Пользовательский интерфейс приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript".

Коротко говоря, принцип "прежде всего содержимое, и лишь затем внешнее оформление" подразумевает создание эффекта погружения в содержимое для пользователя, работающего с приложением, вместо того, чтобы отвлекать его на несущественные детали. В проектировании приложений для Магазина Windows особое внимание уделяется пустому пространству вокруг содержимого и между отдельными его блоками, которое служит для организации и группировки содержимого без необходимости в линиях и рамках. Обычно прозрачные "рамки из пустого пространства" помогают взгляду пользователя притягиваться к содержимому, которое имеет значение. В дизайне приложений для Windows используются принципы типографики (размер шрифта, его насыщенность, цвет и так далее) для создания ощущения структуры, иерархии и сравнительной важности различного содержимого. Это так по той причине, что текст на странице - это уже содержимое, почему бы не использовать его характеристики - типографику - для того чтобы достичь тех же целей, которые обычно достигаются за счёт внешних элементов оформления? (Если говорить об общем стиле макета, широкое использование шрифта Segoe UI в дизайне приложения не является жёстким правилом, скорее начальной точкой. Применение однородных наборов параметров шрифтов (type ramp) для различных заголовков важнее, нежели сами шрифты).

В качестве примера, на Рис. 6.1 показан типичный дизайн настольного или веб-приложения для чтения RSS-лент. Обратите внимание на постоянные элементы внешнего оформления сверху и снизу: команда поиска, закладки для навигации, элементы управления для навигации и так далее. Это занимает примерно 20% пространства экрана. В том, что остаётся примерно две трети занимают служебные элементы, оставляя лишь 20-25% на содержимое, которое нам действительно нужно - на статью.

Рис. 6.2 показывает приложение для тех же целей, дизайн которого соответствует дизайну для Магазина Windows. Обратите внимание на то, как вспомогательные команды убраны с основного экрана. Поиск можно выпонить с помощью чудо-кнопки Поиск. Настроить параметры можно посредством чудо-кнопки Параметры. Добавление новых лент, обновление, навигация - реализованы на панели приложения. А переключение между режимами просмотра реализовано на основе контекстного масштабирования. Для отражения иерархии содержимого используется типографика вместо элементов управления, изображающих папки. В итоге, для содержимого доступна большая часть экрана - около 75%. В результате, мы можем увидеть гораздо больше содержимого, чем раньше, что создаёт гораздо более глубокий и захватывающий опыт взаимодействия пользователя и приложения. Не так ли?

(рис 6.1) Дизайн типичного настольного или веб-приложения, основанный на элементах оформления, которые отображаются за счет полезного содержимого (рис 6.2) То же самое приложение, что и на Рис. 6.1., преображенное с использованием нового подхода к дизайну Windows-приложений, где большая часть элементов оформления исчезает, оставляя гораздо больше места для содержимого. В альтернативном варианте такого дизайна изображения могут выделяться сильнее, чем текст

Даже там, где применяются правила типографики, дизайн для Windows приветствует использование различных размеров шрифта, набора типографских параметров, для того, чтобы создать ощущение иерархии. Таблиц стилей WinJS по умолчанию - ui-light.css и ui-dark.css - предоставляют четыре фиксированных размеров шрифта, где каждый следующий уровень пропорционально больше предыдущего (42 пункта = 80 пикселей, 20 пунктов = 40 пикселей и так далее, как показано на Рис. 6.3. Эти пропорции позволяют пользователю легко, с одного взгляда, выяснять и понимать структуру содержимого. Опять же, это касается привычек и мышечной памяти, и исследования Microsoft показали, что без подобной разницы в размерах, пользователь обычно не может чётко определить роль того или иного содержимого в общей иерархии.

(рис 6.3) Набор типографских параметров в дизайне приложений для Магазина Windows, показанный для таблиц стилей ui-light.css (слева) и ui-dark.css (справа)

Внутри основного содержимого дизайн для Windows приветствует следующие принципы построения макетов:

  • Позвольте содержимому располагаться от края до края.
  • Помните об эргономике: осуществляйте сдвиг содержимого вдоль длинного края области просмотра (обычно горизонтального в альбомном режиме, вертикального - в прикрепленном, и, возможно, в портретном).
  • Осуществляйте сдвиг содержимого только по одной оси, что создаёт ощущение стабильности и позволяет использовать жест скольжения по диагонали для выделения (как в случае с элементом управления ListView), или используйте ограничители (rails) для ограничения направления сдвига одной осью.
  • Выравнивайте содержимое, создавайте структуру, чёткость, следуя общему стилю Windows 8, выравнивая элементы по сетке для их единообразного расположения. Обратитесь снова к материалу "Создание макета приложения" (http://msdn.microsoft.com/library/windows/apps/hh872191.aspx). Здесь показано, что позволяет глазам пользователя принимать что-то за приложение для Магазина Windows без необходимости размышлять об этом, что создаёт ощущение того, что пользователь знаком с приложением и чувствует себя в нём уверенно.
  • Как мы упоминали выше, шаблоны проектов в Visual Studio и Blend созданы с учётом этих принципов, и, таким образом, предоставляют удобную стартовую точку для приложений. Даже если вы начинаете с шаблона Пустое приложение, другие, наподобние шаблона Приложение таблицы, будут служить справочным материалом. Именно это мы сделали с приложением "Here My Am!" в лекции 2.

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

    Быстрый старт: Сдвигаемые разделы и точки прикрепления

    В лекции 5 мы потратили некоторое время на разговор о том, когда ListView - это правильный выбор, а когда - нет. Один из главных случаев, когда разработчики неоправданно пытаются использовать ListView, заключается в реализации домашней страницы или хаба приложения, который содержит множество различных групп содержимого, организованных в столбцы, как показано на Рис. 6.4 и разъяснено в материале "Проектирование навигации для приложений Магазина Windows" (http://msdn.microsoft.com/library/windows/apps/hh761500.aspx). На первый взгляд это выгдялит как ListView, но так как данные, на самом деле, не являются коллекцией, это лишь макет, выводящий фиксированное содержимое, в итоге, имеет смысл использовать для подобной работы HTML и CSS, через метод проб и ошибок.

    Я особо обратил на это ваше внимание, так как все отличные элементы управления, которые предоставляет WinJS, позволяют просто забыть о том, что всё, что вы знаете об HTML и CSS, всё еще применимо в приложениях для Магазина Windows. В конце концов, эти элементы управления - лишь блоки HTML и CSS с некоторыми дополнительными методами, свойствами и событиями.

    (рис 6.4) Макет типичной домашней страницы (хаба) приложения для Магазина Windows с фиксированным заголовком (1) и горазонтально сдвигаемым разделом (2), и разделами или категориями содержимого (3)

    Создание макета хаба

    Посмотрим, как использовать HTML и CSS для того, чтобы реализовать раздел стартовой страницы приложения (хаба), который поддерживает сдвиг, как на Рис. 6.4. Вспомнив, для начала, к материалу "Создание макета приложения" (http://msdn.microsoft.com/library/windows/apps/hh872191.aspx), мы можем сказать, что отступ между группами должен составлять четыре единицы по 20 пикселей каждая, то есть - 80 пикселей. Большинству групп следует иметь квадратную форму, за исключением второй, ширина которой вдвое меньше. Основываясь на размерах дисплея, 1366х768, высота каждого раздела должна составлять 768 пикселей минус 128 пикселей (это место для заголовка), минус, как минимум, 50 пикселей снизу. В итоге остаётся 590 пикселей (если мы добаим заголовки групп для каждого раздела, нужно будет вычесть еще 40 пикселей). В итоге, квадратная группа на базовом дисплее будет иметь 590 пикселей в ширину (мы установили реальную высоту в 100% содержащей её ячейки сетки). Полная ширина раздела будет, таким образом, (590*4 полноразмерных раздела)+(295*один раздел половинной ширины)+(80*4 разделительные пустые пространства). Результат равняется 2975 пикселей. К этому мы добавим колонки по краям - 120 пикселей слева (в соовтетствии с общим стилем Windows) и 80 пикселей справа. В итоге, мы получаем 3175 пикселей.

    Для того, чтобы создать раздел с подобным макетом, мы можем использовать CSS-сетку внутри элемента-контейнера. Для того, чтобы это увидеть, запустим Blend, создадим новый проект с шаблоном Приложение навигации (у нас будет базовая страница, но не все вспомогательные страницы, всё будет оформлено в нужном стиле). Внутри элемента section в pages/home/home.html, создадим новый div-элемент и зададим его параметр класс как hubSections:

    <section aria-label="Main content" role="main">
    <div class="hubSections">	
    </div>	
    </section>

    По адресу pages/home/home.css добавим несоколько правил стилей. Зададим параметр overflow-x: auto элементу section, и расположим сетку в div'е hubSections, используем добавление колонок слева и справа для создания отступов (удалив margin-left: 120px из section и добавив это в качестве первого столбца в div):

    .homepage section[role=main] {
    overflow-x: auto;
    }
    .homepage .hubSections { 
    width: 2975px; 
    height: 100%; 
    display: -ms-grid;
    -ms-grid-rows: 1fr 50px;
    -ms-grid-columns: 120px 2fr 80px 1fr 80px 2fr 80px 2fr 80px 2fr 80px;
    }

    Применив эти стили, мы уже можем увидеть, как начальная страница принимает форму, уменьшив масштаб отображения данных на монтажной панели:

    Теперь создадим отдельные разделы в pages/home/home.html, каждый из них представляет собой div.

    <section aria-label="Main content" role="main">
    <div class="hubSections">	
    <div class="hubSection1"></div>	
    <div class="hubSection2"></div>	
    <div class="hubSection3"></div>	
    <div class="hubSection4"></div>	
    <div class="hubSection5"></div>	
    </div>	
    </section>

    И стилизуем их в соответствии с занимаемыми ими ячейками сетки, в 100% по ширине (width) и высоте (height). Я показал здесь hubSection1, другие выглядят точно так же, имея лишь другие номера столбцов (4, 6, 8 и, соответственно, 10).

    .homepage .hubSection1 {	
    -ms-grid-row: 1;	
    -ms-grid-column: 2; /* 4 для hubSection2, 6 для hubSection3, и так далее. */
    width: 100%;	
    height: 100%;	
     }

    Создание макетов разделов

    Сейчас мы можем взглянуть на содержимое каждого раздела. В зависимости от того, что вы хотите отобразить, и как отображенные разделы должны взаимодействовать, вы можете снова просто использовать макет (CSS-сетку, или, возможно, гибкое окно), или использовать элементы управления наподобие ListView. Разделы hubSection3 и hubSection5 имеют пустые пространства в низу, поэтому они могут быть элементами управления ListView с изменяющимся количеством элементов. Обтатите внимание на то, что если мы создаём список с более чем 9 или 6 элементами, соответственно, мы захотим, настроить размеры столбцов во всей сетке, захотим сделать ширину элемента section больше, но давайте предположим, что дизайн требуется для максимум 6 и 9 элементов в разделах.

    Скажем так же, что мы хотим, чтобы каждый из разделов был интерактивен, когда прикосновение к элементу запускает навигацию к странице детальной информации. (В этом примере не показаны заголовки групп, используемые для навигации к странице группы). Мы просто используем ListView в каждом из разделов, где каждый из ListView будет иметь собственный источник данных. Для hubSection1 нам понадобится использовать объединение ячеек, в остальных же группах вполне подойдут декларативные шаблоны. Ключевое соглашение, касающееся всех этих групп, заключается в том, чтобы стилизовать элементы таким образом, чтобы они хорошо вписались в базовые размеры, которые мы используем. И, возвращаясь к общему стилю приложения, расстояние между изображениями элементов должно быть 10 пикселей, расстояние между столбцами со смешанным содержимым (hubSection4 и hubSection5) должно быть 40 пикселей (что может быть установленно с помощью подходящих CSS-полей).

    Подсказка. Если вы хотите сделать определенные области вашего содержимого невыделяемыми, используйте атрибут -ms-user-select в CSS для элемента div. Обратитесь к примеру: "Невыделяемые области содержимого с CSS-атрибутом -ms-user-select" (http://code.msdn.microsoft.com/windowsapps/Unselectable-content-areas-963eccd9).

    Точки прикрепления

    Если вы запустите упражнение HubPage и поработаете немного с ним, используя жесты инерционной прокрутки (то есть, такие, когда сдвиг элемента продолжается даже после того, как вы убрали палец; подробнее об этом - в лекции 3 курса "Пользовательский интерфейс приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript"), вы заметите, что сдвиг может остановиться в любом месте. Вам и вашему дизайнеру это может понравится, но во многих сценариях имеет смысл автоматическая остановка сдвига на границе раздела или группы. Для сенсорного взаимодействия это можно реализовать с использованием CSS-стилей для точек прикрепления (snap points), как описано в нижеприведенной таблице. Это - стили, которые вы добавляете к элементу, поддерживающему сдвиг, вместе со стилями, отвечающими за переполнение, иначе они не окажут нужного воздействия. Документацию по этому вопросу (и по некоторым другим) можно найти в материале "Сенсорное взаимодействие: изменение масштаба и сдвиг" (http://msdn.microsoft.com/ru-ru/library/windows/apps/hh453816.aspx).

    СтильОписаниеСинтаксис значений
    -ms-scroll-snap-points-xЗадаёт точку прикрепления для оси Х snapInterval(start<length>, step<length>) | snapList(list<lengths>)
    -ms-scroll-snap-points-yЗадаёт точку прикрепления по оси YsnapInterval(start<length>, step<length>) | snapList(list<lengths>)
    -ms-scroll-snap-typeЗадаёт, точка прикрепления какого типа должна быть использована для элемента: none отключает точку прикрепления, mandatory всегда осуществлять сдвиг до остановки на точке прикрепления (что включает в себя окончание инерционного сдвига), и proximity воздействовать на процесс сдвига лишь в том случае, если движение, на самом деле, заканчивается "очень близко" к точке прикрепления. Использование mandatory, таким образом, приводит к сдвигу с шагом в один раздел/элемент, в то время, как proximity позволит "проскочить" очередную точку прикрепления при инерционном сдвиге. Так же обратите внимание на то, что перетаскивание пальцем (то есть, использование жеста, где нет инерционного движения) позволяет пользователю передвинуть элемент в позиции, отличающиеся от точек прикрепления.none | proximity | mandatory
    -ms-scroll-snap-xСокращение для комбинации -ms-scroll-snap-type и -ms-scroll-snap-points-x<-ms-scroll-snap-type> <-ms-scroll-snap-points-x>
    -ms-scroll-snap-yСокращение для комбинации -ms-scroll-snap-type и -ms-scroll-snap-points-y<-ms-scroll-snap-type> <-ms-scroll-snap-points-y>

    В таблице, <length> - это число с плавающей запятой, за которым следует указатель абсолютной единицы (cm, mm, in, pt или pc), или относительной единицы измерения (em, ex или px).

    Для того, чтобы добавить точку прикрепления к каждому из разделов нашей стартовой страницы, нам лишь нужно добавить два стиля точек прикрепления после overflow-x:

    .homepage section[role=main] {	
    overflow-x: auto;	
    -ms-scroll-snap-type: mandatory;	
    -ms-scroll-snap-points-x: snapList(0px, 670px, 1045px, 1715px, 1795px);
    }

    Обратите внимание на то, что показанные здесь точки прикрепления включают 120-пиксельную левую границу, таким образом, каждая выравнивается с разделом, расположенным под текстом заголовка. Таким образом, точка прикрепления 0px соответствует первому разделу, 670px - второму (80-пиксельный разделитель и 590-пиксельная ширина первого раздела) и так далее. Последняя точка прикрепления в 1895px, однако, не следует этому правилу, так как div не может быть сдвинут за эту точку. Это означает, что мы прикрепляем точку где-то в предпоследней секции, но отображаем последнюю секцию и её 80-пиксельную границу.

    После этих изменений, мы обнаружите, что при прокрутке осуществляются остановки (приятно анимированные) точно на границах разделов. Отметьте, что для стартовой страницы, наподобие этой, использование точек прикрепления типа proximity обычно подходит больше. Обязательные точки прикрепления (mandatory) предназначены больше для элементов, с которыми невозможно взаимодействовать или работать без того, чтобы видеть их целиком, как, например, при пролистывании наборов фотографий, статей и так далее. (Элемент управления FlipView это использует).

    Для того, чтобы узнать об этом больше, в том числе - о некоторых других стилях -ms-scroll-* и -ms-content-zoom-*, об ограничителях прокрутки, обратитесь к примеру: "HTML-прокрутка, сдвиг, изменение масштаба" (http://code.msdn.microsoft.com/windowsapps/Scrolling-panning-and-47d70d4c). Обратите, так же внимание на то, что точки прикрепления предназначены не только для использования с элементом управления ListView, они предназначены и для использования в ваших собственных макетах.

    Разные состояния просмотра приложения

    Если в чем-то, касающимся макета приложения для Магазина Windows, и можно быть уверенным, так в том, что режим его отображения, весьма вероятно, будет часто меняться. Во-первых, авто-поворот экрана, особенно, на планшетных, переносных устройствах - делает очень простым и быстрым переключение между альбомной и портретной ориентациями экрана (пользователю не придётся столкнуться с настройкой драйвера дисплея). Во-вторых, устройство может быть подключено к внешнему дисплею, а это означает, что приложение нуждается в самостоятельной настройке на различные разрешения, и, возможно, на различные плотности пикселей. В-третьих, у пользователя есть возможность, в альбомном режиме, "прикреплять" приложение у левой или правой части экрана, когда прикрепленное приложение отображается в области шириной в 320 пикселей, а другое приложение выводится в зоне "заполняющего" просмотра, занимая остаток дисплея. Это можно сделать, используя жесты, мышь, или используя сочетания клавиш Win+. (точка), Win+> (Shift+точка). (Для прикрепленного режима требуется, как минимум, дисплей с разрешением 1366х768, иначе он будет отключен).

    Вам, определенно, захочется протестировать своё приложение со всеми этими вариантами: состояния просмотра, размеры дисплеев, плотностью пикселей. Работу в разных состояниях просмотра можно тестировать напрямую, на любом компьютере, а вот для двух последних вариантов нужны специальные инструменты, которые предоставляют имитатор Visual Stuido и закладка Устройство (Device) в Blend ,позволяя вам имитировать различные условия. Нас сейчас интересует вопрос, как приложение будет действовать при различных условиях просмотра.

    Состояния просмотра

    В лекции 1 были представлены четыре состояния просмотра, вспомнить о них вы можете, посмотрев на Рис. 1.6. Добавим сейчас следующий уровень точности к их описанию, рассмотрев следующую таблицу. Она включает в себя изображения пространства, которое занимают приложения, описания состояний просмотра и идентификаторов этих состояний и в WinRT (в перечислении Windows.UI.ViewManagement.ApplicationViewState (http://msdn.microsoft.com/library/windows/apps/windows.ui.viewmanagement.applicationviewstate.aspx), и в характеристике -ms-view-state (http://msdn.microsoft.com/library/windows/apps/hh465826.aspx) CSS-медиазапросов.

    Пространство, занимаемое приложением (Голубое)Подробности
    Приложение занимает весь экран в альбомном режиме. WinRT: fullScreenLandscape -ms-view-state: fullscreen-landscape
    Приложение занимает либо левую, либо правую часть экрана в альбомном режиме, на области, ограниченной шириной в 320 пикселей. Это означает, что вам не нужно создавать дизайн для всех возможных размеров среди прикрепленных, заполненных (смотрите ниже) и полноэкранных состояний просмотра. WinRT: snapped -ms-view-state: snapped
    Приложение занимает область экрана, находящуюся рядом с прикрепленным приложением. Ширина области, доступной приложению, равняется ширине экрана за вычетом 320 пикселей и 22 пикселей для элемента-разделителя. WinRT: filled -ms-view-state: filled
    Приложение в портретном режиме WinRT: fullScreenPortrait -ms-view-state: fullscreen-portrait

    Снова хочу напомнить, что каждую страницу вашего приложения нужно подготовить для всех четырех режимов просмотра (с некоторыми исключениями, которые описаны во врезке "Предпочтительная ориентация и блокировка ориентации"). Режимы просмотра всегда находятся под контролем пользователя, поэтому любая страница может оказаться в любом режиме просмотра в любое время, даже при старте. Повторяйте этот как мантру, так как многие разработчики и дизайнеры об этом забывают!

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

    Дизайн приложения, таким образом, включает все режимы просмотра для каждой страницы, так же, как мы поступили с описаниями страниц "Here My Am!" в лекции 2. В то же время, обработка режимов просмотра для каждой страницы не подразумевает четыре разных реализации приложения. Режимы просмотра это не более чем разные визуальные представления одного и того же содержимого страниц, как описано в "Руководстве по прикрепленному и заполненному представлениям" (http://msdn.microsoft.com/library/windows/apps/hh465371.aspx). Таким образом, переключение между режимами просмотра всегда сохраняет состояние приложения и его страниц - оно никогда не изменяет режим работы приложения или не осуществляет навигацию на другую страницу. Единственное исключение из этого правила сущестует, если приложение по веским причинам не может работать в прикрепленном режиме (как, например, игра, которой нужно определенное экранное пространство). В таком случае приложение может вывести сообщение об этом, вместе с инструкцией вроде "Прикоснитесь здесь, чтобы продолжить", что позволяет пользователю выразить таким образом своё намерение. В ответ на команду пользователя, приложение может вызвать tryUnsnap - это единственный программный API, который может воздействовать на состояния просмотра. Состояния просмотра, другими словами, всегда меняются по инициативе пользователя, и нет API для установки состояний просмотра, и нет способа для того, чтобы задавать их при запуске приложения.. Не используйте, однако, эту возможность для того, чтобы "срезать углы". Попытайтесь сохранить как можно больше возможностей приложения в прикрепленном режиме.

    Подсказка. Воспринимайте прикрепленный режим просмотра как дополнительный, ценный режим, где основная информация страницы по-настоящему заметна. Другими словами, рассматривайте прикрепленный режим как возможность, а не как тяжёлое бремя.

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

    Врезка: Предпочтительная ориентация и блокировка ориентации

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

    Для ясности, приложение всё еще должно работать в трех режимах: полноэкранном альбомном, в режимах заполняющего и прикрепленного просмотра. Предпочтительная ориентация обычно касается выбора между альбомной и портретной, и это влияет на ориентацию экрана-заставки и других страниц приложения. Это, кроме того, позволяет автоматически менять режим отображения, когда вы перелючаетесь между вашими приложениями и другими, у которых нет похожих предустановок.

    Для того чтобы сообщить Windows об этих предустановках, установите подходящие флаги в группе параметров Поддерживаемые ориентации (Supported Orientations) на закладке Интерфейс приложения (Application UI) в редакторе манифеста:

    Множество подробностей о том, как всё это работает, можно найти в справке по InitialRotationPreference (http://msdn.microsoft.com/library/windows/apps/Hh700342.aspx). Я хочу, кроме того, расссказать о свойствах Windows.Graphics.Display.DisplayProperties.autoRotationPreferences (http://msdn.microsoft.com/library/windows/apps/windows.graphics.display.displayproperties.autorotationpreferences.aspx) и currentOrientation (http://msdn.microsoft.com/library/windows/apps/windows.graphics.display.displayproperties.currentorientation.aspx) дл программного управления ориентацией. Для демонстрации, обратитесь к примеру "Предустановки автоповорота устройства" (http://code.msdn.microsoft.com/windowsapps/Auto-Rotation-Preferences-87ae2902).

    Обработка состояний просмотра

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

    Лучше всего думать о состояниях просмотра в терминах видимости элементов, их размеров, взаимного расположения на странице. При таком подходе, основная часть работы может быть выполнена посредством CSS-медиа запросы с использованием возможности -ms-view-state. Мы видели это в приложении "Here My Am!" из лекции 2. Шаблон проекта Приложение таблицы так же это демонстрирует. Вот как этим медиа-запросы выглядят в CSS:

    @media screen and (-ms-view-state: fullscreen-landscape) {
    /* ... */
    }
    
    @media screen and (-ms-view-state: filled) {
    /* ... */
    }
    
    @media screen and (-ms-view-state: snapped) {
    /* ... */
    }
    
    @media screen and (-ms-view-state: fullscreen-portrait) {
    /* ... */
    }
    
    /* Синтаксис для комбинирования медиа-запросов (разделены запятыми) */	
    @media screen and (-ms-view-state: fullscreen-landscape),
    
    screen and (-ms-view-state: fullscreen-portrait), screen and (-ms-view-state: filled) {
    /* ... */	
    }

    Кроме того, весьма разумно добавить другие выражения к этим запросам, такие, как and (min-width: "1600px"), так как вы можете выполнять множество различных настроек, основываясь на разрешении экрана.

    Для приложений Магазина Windows применяйте возможности обработки режимов просмотра в медиа-запросах вместо состояний, хранящихся в свойстве CSS Таким образом, состояния просмотра не сообщаются страницам, загруженным в iframe, в веб-контексте. Подобные страницы могут использовать стандартные CSS-медиа запросы для того, чтобы сделать вывод о состоянии просмотра, или окружающая страница, исполняющаяся в локальном контексте, может передать сведения о состоянии просмотра в iframe с помощью postMessage..

    Например, следуя стандартному алгоритму CSS, и полноэкранный портретный (fullscreen portrait), и прикрепленный (snapped) режимы детектируются как orientation: portrait, так как соотношение сторон экрана в таких режимах указывает на его вертикальное расположение. Однако, прикрепленный режим подразумевает иное намерение пользователя, чем полноэкранный портретный. В прикрепленном режиме вы скорее хотите видеть наиболее важные части приложения, нежели копию портретного макета в пространстве шириной 320 пикселей.

    Обычный подход заключается в том, чтобы размещать правила, касающиеся полноэкранного альбомного режима просмотра, в верхней части CSS-файла и затем выполнять тонкие настройки внутри конкретных медиа-запросов. Мы сделали это с "Here My Am!" в лекции 2, где стиль по умолчанию работает для режимов fullscreen-landscape и filled, и нам нужно было задать специфические правила лишь для режимов snapped и fullscreen-portrait.

    Совет. При стилизации приложения в Blend, в панели Правила стилей (Style Rules)существуют интуитивно понятные визуальные подсказки, которые позволяют контролировать точную точку вставки любого нового CSS-стиля в заданной таблице стилей. С помощью этого средства, которое выглядит как оранжевая линия на рисунке ниже, и как показано в Video 2.2., вы можете указать точное место вставки стилей для конкретных медиа-запросов внутри медиа-запроса.

    В некоторых случаях обработка медиа-запросов в декларативном CSS недостататочна. Когда основное содержимое отображается на странице, содержащей ListView с макетом gridLayout, которая прокручивается в горизонтальном направлении, обычно макет переключают на ListLayout при переходе в прикрепленный режим. Вы можете, кроме того, как показано в материале: "Руководство по прикрепленному и заполненному представлениях" (http://msdn.microsoft.com/library/windows/apps/hh465371.aspx), преобразовать список кнопок в единый выпадающий элемент select для того, чтобы предложить пользователю те же функциональные возможности посредством более компактного пользовательского интерфейса. Для реализации подобного вам понадобится JavaScript.

    Для подобных целей вы можете задействовать стандартное Media Query Listener API в JavaScript. Данный интерфейс (часть W3C CSSOM View Module, http://dev.w3.org/csswg/cssom-view/) позволяет вам добавлять обработчики к изменениям состояний медиа-запросов. Для того, чтобы прослушивать событие перехода в режим прикрепленного просмотра, вы можете использовать код, подобный этому:

    var mql = window.matchMedia("(-ms-view-state: snapped)");
    mql.addListener(styleForSnapped);
    function styleForSnapped() {
    if (mql.matches) {	
    //...	
    }
    
    // Создайте прослушиватели для других состояний просмотра: full-screen, fill, и device-portrait
    // или обработайте все меди-запросы в едином обработчике, проверяя в нём текущее состояние просмотра.

    Вы можете видеть, что строка медиа-запроса, которую передают в window.matchMedia, это та же строка, котрая используется в CSS, и в обработчике вы, конечно, можете сделать всё, что нужно с помощью JavaScript.

    Совет. Убедитесь в том, что протестировали режимы просмотра приложения при возникновении события resuming, так как характеристики дисплея могут измениться, например, при подключении другого монитора или увеличение экранных элементов, выполненного с помощью команды панели чудо-кнопок Параметры > Изменение параметров компьютера > Специальные возможности (Settings > Change PC Setings > Ease of Access), которая ведет к окну, содержащему тумблер Увеличить все элементы на экране (Make Everything on the Screen Bigger). Воззможно, что ваше приложение будет восстановлено из фонового режима (из приостановленного состояния) в прикрепленный режим просмотра, пока ваше приложение приостановлено, могут поменяться размеры экрана. Поэтому тестируйте макет на корректную обработку события resuming при открытии приложения в прикрепленном режиме просмотра и при изменении параметров экрана.

    Обрабатывая изменения режимов просмотра (или события window.onresize), вы можете получить точные размеры окна приложения посредством свойств window.innerWidth и window.innerHeight. Свойства document.body.clientWidth и document.body.clientHeight позволяют узнать ту же информацию, что и из свойств clientWidth и clientHeight любого элемента (наподобие div), который занимает 100% тела документа. Внутри события resize так же доступны свойства args.view.outerWidth и args.view.outerHeight.

    В CSS так же доступны сведения о высоте и ширине окна просмотра (vh и vw, соответственно). Вы можете поставить перед ними префикс в виде процентов, например, 100vh - это 100% высоты окна просмотра, и 3.5vw - это 3.5% ширины окна просмотра. Эти переменные так же могут быть использованы в выражениях CSS calc.

    Текущий режим просмотра доступен посредством свойства Windows.UI.ViewManagement.ApplicationView.value. Его значения берутся из перечисления Windows.UI.ViewManagement.ApplicationViewState, как показано в вышеприведенной таблице. В предыдущих лекциях мы видели применение этих механизмов. Например, элементы управления страниц (речь о них шла в лекции 3) обычно проверяют состояние просмотра в их методе ready и напрямую получают эти состояния в своём методе updateLayout. На самом деле, каждый метод элемента управления страницы groupedItem в проекте Приложение таблицы чувствителен к изменению состояния просмотра. Взгляните на код, взятый из pages/groupedItems/groupedItems.js:

    // Несколько строк и комментариев опущено	
    var appView = Windows.UI.ViewManagement.ApplicationView;	
    var appViewState = Windows.UI.ViewManagement.ApplicationViewState;
    var nav = WinJS.Navigation;	
    var ui = WinJS.UI;	
    
    ui.Pages.define("/pages/groupedItems/groupedItems.html", {
    initializeLayout: function (listView, viewState) {
    if (viewState === appViewState.snapped) { listView.itemDataSource = Data.groups.dataSource; listView.groupDataSource = null;
    listView.layout = new ui.ListLayout();
    } else {
    listView.itemDataSource = Data.items.dataSource;
    listView.groupDataSource = Data.groups.dataSource;
    listView.layout = new ui.GridLayout({ groupHeaderPosition: "top" });
    }
    },
    
    itemInvoked: function (args) {
    if (appView.value === appViewState.snapped) {
    // Если страница в прикрепленном режиме, пользователь вызывает группу. 
    var group = Data.groups.getAt(args.detail.itemIndex); nav.navigate("/pages/groupDetail/groupDetail.html", { groupKey: group.key });
    } else {
    // Если страница не в прикрепленном режиме, пользователь активирует элемент. 
    var item = Data.items.getAt(args.detail.itemIndex); nav.navigate("/pages/itemDetail/itemDetail.html",
    { item: Data.getItemReference(item) });
    }
    },
    
    ready: function (element, options) {
    // ...	
    this.initializeLayout(listView, appView.value);
    // ...	
    },	
    // Эта функция обновляет макет страницы в ответ на изменения viewState. 
    updateLayout: function (element, viewState, lastViewState) {
    var listView = element.querySelector(".groupeditemslist").winControl;
    if (lastViewState !== viewState) {
    if (lastViewState === appViewState.snapped ||
    viewState === appViewState.snapped) {
    var handler = function (e) {
    listView.removeEventListener("contentanimating", handler, false);
    e.preventDefault();
    }
    listView.addEventListener("contentanimating", handler, false);
    this.initializeLayout(listView, viewState);
    }
    }
    }
    }
    });

    В первую очередь, метод initializeLayout, который вызывается и из ready и из updateLayout проверяет текущее состояние просмотра и соответствующим образом настраивает элемент управления ListView. Если вы помните из лекции 5, во время исполнения программы можно и настраивать ListView и менять его источник данных. Здесь мы используем ListLayout со списком групп в прикрепленном состоянии просмотра и gridLayout со сгруппированными элементами в других режимах. Это показывает, как мы показываем то же самое содержимое, но в более сжатом формате, скрывая отдельные элементы в прикрепленном режиме. Из-за этого itemInvoked так же проверяет режим отображения, так как элементы списка - это группы в прикрепленном режиме и в таком случае навигация осуществляется на страницу сведений о группе вместо перехода на страницу детальной информации об элементе.

    Что касается updateLayout, он активируется из обработчика события window.onresize в коде PageControlNavigator (смотрите js/navigator.js в шаблоне проекта Приложение таблицы). Этот обработчик передаёт сведения о новом и предыдущем состоянии просмотра в updateLayout. Если эта функция обнаруживает, что мы переключились в прикрепленный режим или переключились из него, она сбрасывает к исходному состоянию ListView посредством initializeLayout. И, так как мы меняем источник данных ListView, здесь нет нужды в воспроизведении анимации входа или перехода. Небольшая уловка, работающая с событием contentanimating просто подавляет анимацию.

    Врезка: Физическая ориентация экрана

    Полноэкранный альбомный и полноэкранный портретный режимы просмотра предоставляют некоторую информацию о том, как устройство, на самом деле, ориентировано в пространстве, но подобная информация может быть гораздо точнее получена из свойств объекта Windows.Graphics.Display.DisplayProperties (http://msdn.microsoft.com/library/windows/apps/windows.graphics.display.displayproperties.aspx). В частности, свойство currentOrientation содержит значение из перечисления Windows.Graphics.Display.DisplayOrientations (http://msdn.microsoft.com/library/windows/apps/windows.graphics.display.displayorientations.aspx), что показывает, как устройство повёрнуто по отношению к nativeOrientation (и вызывает, при необходимости, событие orientationchanged). Эти данные позволят вам узнать, например, находится ли устройство экраном вниз, по отношению к небу, что может быть полезным для любого приложения, реализующего дополненную реальность, такую, как звёздная карта.

    Похожим образом, API Windows.Devices.Sensors (лекции 3 курса "Пользовательский интерфейс приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript".

    Размер экрана, плотность пикселей и масштабирование

    Не знаю о вас, но я, когда впервые узнал, что зона прикрепленного просмотра всегда имеет 320 пикселей в ширину - реальных пикселей, а не некое значение, выраженное в процентном выражении от ширины экрана - это меня озадачило. Не даст ли это совершенно разные впечатления от программы на разных дисплеях? Ответ на этот вопрос отрицательный. 320 пикселей - это около 25% от базового размера монитора 1366х768, что означает, что оставшиеся 75% - это вполне знакомые нам 1024х768. На 10-дюймовом дисплее это примерно 2.5 дюйма физического пространства дисплея. Пока всё понятно.

    На более крупных мониторах, с другой стороны, таких, как 2560x1440, эти 320 пикселей займут лишь 12,5% ширины, таким образом, макет полного экрана выглядит совершенно иначе. Однако, учитывая то, что подобные мониторы имеют 24-дюймовую диагональ, эти 320 пикселей снова занимают примерно 2.5 дюйма физического пространства экрана, что означает, что зона прикрепленного просмотра выглядит так же, как и ранее. Она лишь имеет больше вертикального пространства и оставляет после себя больше свободного места на экране.

    Это приводит нас к вопросу о плотности пикселей (pixel density). Что произойдёт, если ваше приложение окажется на по-настоящему маленьком дисплее, имеющем высокое разрешение? Очевидно, что на подобном дисплее зона в 320 пикселей будет немногим более дюйма. Есть у кого-нибудь увеличительное стекло?

    К счастью, это не тот вопрос, о котором беспокоятся приложения для Магазина Windows… Почти. Основное преимущество, которое получает пользователь от подобного дисплея - это более высокая чёткость изображения, но не большая плотность информации. Сенсорные цели должны быть одинаковых размеров на мониторах любых размеров, не важно, сколько пикселей они занимают. Ведь человеческие пальцы не меняются с развитием технологий! Для того, чтобы это учитывать, Windows автоматически уменьшает масштаб эффективного разрешения, которое сообщается приложению, что означает, что любые координаты, которые вы используете внутри приложения (в HTML, CSS и JavaScript) автоматически масштабируются к разрешению того устройства, на котором осуществляется вывод пользовательского интерфейса приложения. Это производится на низком уровне подсистем рендеринга HTML/CSS в хост-процессе приложения, всё выводится в соответствии с особенностями пикселей конкретного устройства для максимальной чёткости изображения.

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

    Разные размеры экрана, разная плотность пикселей может быть протестирована с помощью имитатора в Visual Studio, или на закладке Устройства (Device) в Blend. Последний вариант показан на Рис. 6.5. Здесь отображены применимый DPI и фактор масштабирования. 100% масштаб означает, что приложению напрямую сообщают о разрешении устройства. 140% и 180%, с другой стороны, что означает, что имеет место масштабирование. При размерах экрана 10.6 дюйма, разрешении 2560х1440 и масштабировании в 180%, например, приложение увидит данный экран как экран с размерами 1422х800 (2560/1.8 на 1440/1.8), что очень близко к стандартному дисплею 1366х768. Похожим образом, при размерах экрана 10.6 дюйма и разрешении 1920х1080 масштабирование в 140% покажет приложению экран размером 1371х771 (1920/1.4 на 1080/1.4). И в том и в другом случаях макет, разработанный в расчёте на экран 1366х768 полностью подходит, хотя вы, конечно, можете настроить его так точно, как захотите.

    Совет. Если ваше приложение имеет фиксированный макет (fixed layout) (смотрите раздел "Фиксированные макеты и элемент управления ViewBox" ниже), вы можете разрешить вопрос разной плотности пикселей просто используя графические ресурсы, масштабированные до 200% по отношению к вашему стандартному дизайну. Это так, потому что фиксированный макет может быть масштабирован к произвольным размерам, в итоге, изображения, имеющие изначально масштаб 200% хорошо масштабируются в любом случае. Подобное приложение не нуждается в предоставлении вариантов изображений, которые использует, в масштабах 100%, 140% и 180%. (рис 6.5) Параметры для задания размеров дисплея и плотностей пикселей на закладке Устройство (Device) в Blend

    Как отмечено ранее, работая с состояниями просмотра, вы можете программным способом определять точный размер окна вашего приложения посредством свойств window.innderWidth и window.innerHeight, свойствами document.body.clientWidth и document.body.clientHeight, и свойствами clientWidth и clientHeight любого элемента, который занимает 100% тела страницы. Внутри window.onresize вы можете использовать их (или свойства args.view.outerWidth и args.view.outerHeight) для того, чтобы подстроить макет приложения под изменения, касающиеся общего режима отображения приложения. Конечно, если вы используете что-то наподобие CSS-сетки с дробными размерами строк и столбцов, большинство подобных настроек макета будет выполнено автоматически.

    В любом случае, размер уже отражает автоматическое масштабирование с учетом плотности пикселей, таким образом, это - размеры, под которые вы адаптируете макет. Если вы хотите знать, каковы физические размеры дисплея, с другой стороны, вы можете воспользоваться свойствами window.screen.width и window.screen.height. Другие параметры дисплея можно обнаружить в объекте Windows.Graphics.Display.DisplayProperties (http://msdn.microsoft.com/library/windows/apps/br226143.aspx), в частности, такие, как logicalDPI и текущее значение resolutionScale. Последнее является значением перечисления Windows.Graphics.Display.ResolutionScale (http://msdn.microsoft.com/library/windows/apps/windows.graphics.display.resolutionscale.aspx), среди них - scale100Percent, scale140Percent, и scale180Percent. Возвращаемые значения этих идентификаторов - 100, 140 и 180, таким образом, вы можете использовать resolutionScale напрямую в вычислениях.

    Врезка: Хорошая возможность для удалённой отладки

    Работа с различными возможностями устройств предоставляет хорошую возможность поработать с удалённой отладкой, как описано в материале "Выполнение приложений для Магазина Windows на удаленном компьютере" (http://msdn.microsoft.com/library/windows/apps/hh441469.aspx). Такой подход позволит вам протестировать программу на различных дисплеях без необходимости устанавливать на каждом из устройств Visual Studio, и, кроме того, даст вам преимущества отладки с использованием нескольких мониторов. Вам лишь нужно установить и запустить средства удалённой отладки на целевом устройстве и убедиться, что оно подсоединено с помощью кабеля к той же сети, к которой подключен компьютер, на котором вы выполняете разработку. (Вам может понадобиться приобрести маленький USB-Ethernet-адаптер, если ваше устройство не имеет подходящего порта - удалённая отладка не работает через Интернет и при соединении устройств по беспроводной сети). Монитор удалённой отладки, выполняющийся на удалённой машине, сообщает о себе Visual Studio, исполняющемся на машине разработчика. Обратите внимание на то, что когда вы попытаетесь приступить к удалённой отладке в первый раз, вам предложат получить лицензию разработчика для целевого устройства, таким образом, это устройство должно быть подключено к Интернету в это время.

    Графические элементы, которые хорошо масштабируются

    Различные размеры экранов и плотности пикселей задают приложениям еще одну задачу, не связанную с макетом, касающуюся графических элементов, которые всегда должны выглядеть наилучшим образом. Конечно, вы можете рисовать графические элементы напрямую, используя элемен HTML5 canvas, на что мне хотелось бы обратить ваше внимание, так это на заранее сформированные графические ресурсы.

    Масштабируемая векторная графика HTML5 (scalable vector graphics, SVG) в данном случае очень кстати. Вы включаете встроенный SVG-код в свой HTML (включая фрагменты страниц), или вы можете хранить их в отдельных файлах и ссылаться на них как на атрибуты img.src. Один из самых простых способов использовать SVG - разместить элемент img внутри пропорционально настраиваемой ячейки CSS-сетки и задать стили width и height этого элемента в 100%. SVG автоматически масштабируется для заполнения ячейки, и так как ячейка изменяет размер вместе с элементом, являющимся контейнером для SVG, всё обрабатывается автоматически.

    У такого подхода есть одна проблема - SVG масштабируется с учетом соотношения сторон ячейки CSS-сетки, в которой находится, а оно не всегда может быть таким, как вам нужно. Для того, чтобы управлять этим поведением, убедитесь, что SVG имеет атрибуты viewBox и preserveAspectRatio, где cоотношение сторон, хранящееся в viewBox соответствует тому, которое задано свойствами SVG width и height:

    <svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink" version="1.0"
    width="300"
    height="150" viewBox="0 0 300 150" preserveAspectRatio="xMidYMid meet">

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

    Что касается ресурсов в пакете приложения, мы уже видели, как работать с различными плотностями пикселей в лекции 3, посредством суффиксов к именам файлов .scale-100, .scale-140, и .scale-180. Этот подход работает для любых изображений в вашем приложении, используемых во всех случаях, будь это изображение для экрана-заставки, изображения плиток и другие графические ресурсы, на которые есть ссылки в манифесте. Таким образом, если у вас есть растровое изображение, имеющее имя banner.png, вы создатите три изображения в пакете приложения, которые будут называться banner.scale-100.png, banner.scale-140.png, и banner.scale-180.png. Затем вы можете просто ссылаться на базовое имя элемента в CSS или в конструкциях вида <img src= "images/banner.png"> и background-image: url('images/banner.png'), и загрузчик ресурсов Windows чудесным образом автоматически загрузит изображение, имеющее подходящий масштаб. (Если файлы с суффиксами .scale-* не найдены, загрузчик будет искать файл banner.png). Мы увидим даже больше подобных чудес в лекции 6 курса "Программная логика приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript и их взаимодействие с системой", где мы так же добавим варианты для различных языков и контрастных цветовых схем, которые представляют дополнительные собственные суффиксы.

    Если вам не по душе подобная схема именования файлов, знайте, что вместо этого вы можете использовать похожим образом именованные папки. Таким образом, для реализации этого подхода вам понадобятся папки с именами scale-100, scale-140, и scale-180, расположенные в папке изображений и содержащие файлы с неизмененными именами (наподобие banner.png).

    В CSS вы так же можете использовать медиа-запросы с установками max-resolution и min-resolution для управления тем, какие изображения будут загружены. Помните, однако, что CSS опирается на логическое DPI, а не на физическое DPI, граница для каждого фактора масштабирования указана далее (значения DPI здесь слегка отличаются от тех, которые даны в документации, так как они получены из эмпирических тетстов; документация предлагает, соответственно, значения в 134, 135 и 174 dpi).

    @media all and (max-resolution: 134dpi) {
    /* масштаб 100% */
    }
     
    @media all and (min-resolution: 135dpi) {
    /* масштаб 140% */
    }
    
    @media all and (min-resolution: 174dpi) {
    /* масштаб 180% */
    }

    Как разъяснено в "Руководстве по масштабированию в зависимости от плотности пикселей" (лекцию 2 курса "Программная логика приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript и их взаимодействие с системой", "Плитки, уведомления, экран блокировки и фоновые задачи", раздел "Использование локальных изображений и изображений, полученных из Web" для того, чтобы найти сведения о том, как при обновлении плиток данные механизмы используются для масштабирования, учёта контрастных схем и языковых особенностей.

    Вы можете программным образом получить свойства logicalDpi и resolutionScale из объекта Windows.Graphics.Display.DisplayProperties. Событие logicaldpichanged (событие WinRT) может быть, так же, использовано для проверки изменений resolutionScale, так как эти два параметра всегда связаны. Использование данных API проиллюстрировано примером "Масштабирование в соответствии с DPI" (http://code.msdn.microsoft.com/windowsapps/Scaling-sample-cf072f4f).

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

    Адаптивные и фиксированные макеты для дисплеев различных размеров

    Так же, как каждая страница вашего приложения нуждается в подготовке для различных состояний просмотра, страницы нуждаются и в подготовке для экранов различных размеров. Я рекомендую почитать "Руководство по масштабированию для различных экранов" (http://msdn.microsoft.com/library/windows/apps/hh780612.aspx), где есть ценная информация о том, с дисплеями каких размеров может столкнуться ваше приложение. Из этого руководства мы можем сделать вывод о том, что размер самой маленькой области прикрепленного просмотра равняется 320х768, минимальный размер области заполняющего просмотра - 1024х768, и минимальный размер области полноэкранного просмотра (портретного и альбомного) - 1280х800 и 1366х768. Это - базовые параметры для вашего дизайна.

    Таким образом, дисплеи лишь увеличиваются, по сравнению с базовыми параметрами, в итоге мы приходим к вопросу: "Что делать с дополнительным пространством?". Первая часть ответа заключается в том, чтобы заполнить экран. Ничего не выглядит глупее, чем приложение, запущенное на 27-дюймовом мониторе и использующее при этом лишь область размером 1366х768, для которой оно было разработано. В подобной ситуации приложение займёт лишь от четверти экрана, до, в лучшем случае, половины. Как я уже говорил много раз, представьте себе, какие обзоры и оценки может получить ваше приложение в Магазине Windows, если вы не будете обращать внимание на подобные детали!

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

    Врезка: Параметр "Увеличить все элементы на экране"

    Среди параметров компьютера (чудо-кнопка Параметры > Изменение параметров компьютера > Специальные возможности (Settings > Change PC Setings > Ease of Access)) есть тумблер Увеличить все элементы на экране (Make Everything on the Screen Bigger). Включение этого параметра позволяет эффективно увеличить размер экранных элементов примерно на 40%, что подразумевает то, что система сообщает приложениям о том, что размер экрана примерно на 30% меньше, чем текущее разрешение (похоже на уровень масштабирования в 140%). К сачтью, этот параметр отключён, если в итоге система вынуждена будет сообщить об экране, который меньше, чем 1024х768, в итоге, подобное разрешение - это самое меньшее, на что может рассчитывать ваше приложение. В любом случае, при изменении данного параметра вызывается событие Windows.Graphics.Display.DisplayProperties.logicalDpiChanged.

    Фиксированные макеты и элемент управления ViewBox

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

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

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

    Так как это - более распространённый подход, WinJS предоставляет встроенный элемент управления макетом именно для этой цели: WinJS.UI.ViewBox (http://msdn.microsoft.com/library/windows/apps/br229771.aspx) (не следует путать с атрибутом SVG viewBox). Как и в случае с другими элементами управления WinJS, вы можете объявить его, используя data-win-control в HTML, как показано ниже, где элемент viewBox может содержать один и только один дочерний элемент:

    <div data-win-control="WinJS.UI.ViewBox">
    <div class="fixedlayout">	
    <p>Content goes here</p>	
    </div>	
    </div>

    На самом деле, это всё, на что можно посмотреть при работе с ViewBox. У него нет параметров или свойств, нет методов и событий - всё очень просто! Обратите так же внимание на то, что так как ViewBox - это лишь элемент управления, вы можете использовать для любого содержимого с постоянным соотношением сторон в адаптивном макете. Он предназначен не только для создания макета целой страницы.

    Для установки базисного размера ViewBox - размерностей, на которых будет основан ваш код - просто задайте параметры height и width его дочернего элемента в CSS. Например, для установки базисного размера в 1024х768, мы устанавливаем данные свойства в правиле для класса fixedLayout:

    fixedlayout { width: 1024px; height: 768px;
    }

    Как только создан экземпляр объекта ViewBox, он прослушивает события window.onresize и затем применяет 2D-трансформацию CSS к дочерним элементам, основываясь на разнице между базисным размером и реальным размером. Это позволяет сохранить соотношение сторон. Это работает и для увеличения и для уменьшения масштабов отображения содержимого. Автоматически применяется и размещение полос пустого пространства сверху и снизу или справа и слева от дочернего элемента, вы можете задать внешний вид этих областей (на самом деле, любых областей, которые не перекрывает дочерний элемент), используя класс win-viewbox. Как всегда, используйте данный селектор в области видимости конкретного элемента управления, если вы в приложении пользуетесь более чем одним элементом ViewBox, если только вы не хотите, чтобы подобный стиль был применен ко всем элементам.

    Базовая структура выше - это то, что вы получаете при создании нового приложения по шаблону Приложение с фиксированным макетом в Visual Studio и Blend. Как показано здесь, создаётся макет с базисным размером 1024х768, но вы можете использовать любой желаемый размер.

    CSS для этого шаблона проекта показывает, что вся страница стилизована как гибкое окно CSS для того, чтобы ViewBox был отцентрован, и то, что элементу fixedLayout задана сетка по умолчанию:

    html, body {	
    height: 100%;
    margin: 0;	
    padding: 0;	
     }
    body {	
    -ms-flex-align: center;	
    -ms-flex-direction: column;
    -ms-flex-pack: center;	
    display: -ms-flexbox;	
    }
    .fixedlayout {	
    -ms-grid-columns: 1fr;
    -ms-grid-rows: 1fr;	
    display: -ms-grid;	
    height: 768px;
    width: 1024px;
    }

    Если вы создаете проект по этому шаблону в Blend, добавьте стиль границы к правилу fixedLayout (наподобие border: 2px solid Red;), и поэкспериментируйте с режимами отображения и настройками дисплея на закладке Устройство (Device). Таким образом вы можете понаблюдать за тем, как ViewBox реализует возможности масштабирования без каких-либо усилий с вашей стороны. Для того, чтобы показать это ярче, упражнение fixedLayout для этой лекции содержит измененный на canvas дочерний элемент ViewBox, в котором нарисована сетка 4х3 (соответствующая соотношению сторон экрана 1024х768) из квадратных ячеек размером по 256 пикселей, содержащих окружности. Как показано на Рис. 6.6, квадраты и круги не превращаются в прямоугольники и овалы, когда мы переключаем состояния просмотра и размеры экранов, автоматически добавляются полосы пустого пространства (применяя стиль background-color к классу win-viewbox).

    Врезка: Растровая графика и фиксированные макеты

    Если вы используете с ViewBox растровую графику, настройте их в соответствии с максимальным разрешением 2560х1440, таким образом, они будут хорошо выглядеть на больших дисплеях и будут отображаться с уменьшением масштаба (вместо увеличения) на дисплеях меньшего размера. Вы можете воспользоваться и альтернативным подходом, загружая различные изображения (посредством различных URI для img.src), которые наилучшим образом подходят для наиболее широко распространённых размеров дисплея.

    Обратите внимание на то, что всё еще применимо масштабирование разрешения. Если приложение исполняется на дисплее высокой плотности размером 10.6 дюймов и разрешением 2560х1440 (масштабирование 180%), приложение, и, таким образом, ViewBox опознают такой дисплей как дисплей меньшего размера. Но если вы поддерживаете графические элементы для собственного разрешения устройства, они будут выглядеть чётко при выводе на экран.

    (рис 6.6) Масштабирование фиксированного макета с использованием элемента управления WinJS.UI.ViewBox, показано добавление полос по краям эркрана в полноэкранном режиме 1366х768 (слева) и в прикрепленном режиме просмотра (справа)

    Адаптивные макеты

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

    Подобные макеты легче всего реализовать с использованием CSS-сетки, где пропорциональные строки и столбцы автоматически увеличиваются или уменьшаются; элементы внутри ячеек сетки соответствующим образом подстраивают свои размеры. Это можно наблюдать в шаблонах проектов для Visual Studio и Blend, особенно - в шаблоне Приложение таблицы. На типичном дисплее с разрешением 1366х768 вы можете видеть некоторое количество элементов, как показано в верхней части Рис. 6.7. Переход на 27-дюймовый дисплей с разрешением 2560х1440 позволит вам увидеть гораздо больше данных, это можно видеть в нижней части рисунка.

    (рис 6.7) Адаптивный макет проекта, построенного по шаблону Приложение таблицы, для экрана с разрешением 1366х768 (сверху) и для экрана с разрешением 2560х1440 (снизу)

    Честно говоря, проект Приложение таблицы не выполняет особой обработки макета при изменении размеров экрана, отличающейся от того, что он выполняет для различных режимов просмотра. Из-за использования CSS-сеток и пропорциональных размеров ячеек, ячейка, содержащая элемент управления ListView, автоматически увеличивается. Элемент управления ListView самостоятельно просшушивает событие window.onresize, в итоге, нам не нужно отдельно управлять обновлением его макета.

    Общая стратегия работы с адаптивным макетом, таким образом, не вызывает затруднений:

  • Используйте везде, где возможно, CSS-сетку, для автоматической реализации адаптивного макета.
  • Просшуливание события window.onresize нужно для самостоятельного изменения расположения или размеров элементов, таких, как элемент HTML canvas.
  • Позвольте элементам управления прослушивать событие window.onresize для самостоятельной настойки их параметров. Это особенно важно для элементов управления для коллекций, наподобие ListView.
  • В качестве другого ориентира вы можете воспользоваться примером "Адаптивный макет с использованием CSS" (http://code.msdn.microsoft.com/windowsapps/Adaptive-layout-with-sample-062e7fe2), который применяет тот же подход, что и шаблон проекта Приложение таблицы, полагаясь на самостоятельную подстройку своих параметров элементами управления. В примере, вы увидите, что приложение не выполняет никаких прямых расчётов, основанных на размерах окна.

    Подсказка. Если у вас есть адаптивный макет и вы хотите использовать фоновое изображение, заданное в CSS, которое масштабируется вместе с собственным контейнером (вместо того, чтобы заполнять его, повторяясь), стилизуйте background-size либо задав значение contains, либо 100% 100%.

    Вам, как разработчику, должно быть понятно и то, что то, как приложение работает с экранами различных размеров - это вопрос дизайна. Вышеприведенная стратегия - это то, что вы используете для реализации дизайна, но дизайн определяет то, как всё будет выглядеть. Эти соображения, которых я здесь лишь кратко коснулся, описаны в материале "Руководство по масштабированию для различных экранов" (http://msdn.microsoft.com/library/windows/apps/hh780612.aspx):

  • Какие области являются фиксированными, а какие - адаптивными?
  • Как адаптивные области используют дополнительное пространство, включая подходы, с помощью которых эти области подстраиваются под дополнительное пространство?
  • Как взаимодействуют области с адаптивным макетом и области с фиксированным макетом в каркасе приложения?
  • Как полный макет приложения использует пространство, то есть, как к изменению размера адаптируются свободные пространства, не становится ли содержимое расположенным слишком плотно?
  • Как приложение использует многоколоночный текст?
  • Ответы на подобные вопросы помогут вам понять, как макету следует адаптироваться.

    Использование CSS-сетки

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

    Так как этот курс направлен на особенности разработки для Windows 8, я оставляю задачу разъяснения всех подробностей о сетке спецификациям W3C: http://dev.w3.org/csswg/css3-grid-layout/ и http://www.w3.org/TR/css3-grid-layout/. Эти материалы представляют собой общие руководства, которые помогут в понмании того, как настраиваются размеры строк и столбцов, особенно когда некоторые из них объявлены с фиксированными размерами, кого размер некоторых зависит от содержимого, а другие заданы так, чтобы они заполняли оставшееся пространство. Здесь много тонкостей!

    Так как эти спецификации, когда я пишу это, всё еще находятся в разработке, полезно точно знать, какие части спецификация реально поддерживаются подсистемой HTML/CSS, которой пользуются приложения для Магазина Windows.

    Для элемента, содержащего сетку, поддерживаемые стили весьма просты. Во-первых, используйте модели отображения -ms-grid и -ms-inline-grid (стиль display:). Позже мы вернемся к -ms-inline-grid.

    Во вторых, в элементах сетки используйте -ms-grid-columns и -ms-grid-rows для задания их расположения. Если оставить эти параметры незаданными, значение по умолчанию - это один столбец и одна строка. Поддерживается и синтаксис для задания повторяющихся конструкций, такой, как -ms-grid-columns: (1fr)[3];, что особенно удобно, когда у вас имеется повторяющиеся серии строк или столбцов, которые появляются внутри строк описаний. Как пример, следующие команды эквивалентны:

    -ms-grid-rows:10px 10px 10px 20px 10px 20px 10px;
    -ms-grid-rows:(10px)[3] (20px 10px)[2];	
    -ms-grid-rows:(10px)[3] (20px 10px) 20px 10px;	
    -ms-grid-rows:(10px)[2] (10px 20px)[2] 10px;

    То, как вы задаёте строки и столбцы - вопрос достаточно интересный, так как вы можете сделать некоторые из них фиксированными, некоторые - гибко меняющими размеры, а некоторые - ориентированными на размер содержимого. Этих целей можно достичь, используя следующие значения. Опять же, посмотрите документацию по особенностями использования спецификаторов max-content, min-content, minmax, auto, и fit-content, вместе со значениями, которые задаются в таких единицах измерения, как px, em, %, и fr. Приложения для Магазина Windows, так же, поддерживают, в качестве единиц измерения, такие показатели, как vh (высота окна просмотра) и vw (ширина окна просмотра).

    Внутри сетки, дочерние элементы располагаются в заданных строках и столбцах с заданными характеристиками выравнивания, объединения, расположения по слоям, используя следующие стили:

  • -ms-grid-column - определяет базовый столбец (нумерация начинается с 1) в сетке для дочернего элемента.
  • -ms-grid-row - определяет базовую строку (нумерация начинается с 1) в сетке для дочернего элемента.
  • -ms-grid-column-align и -ms-grid-row-align задаёт то, как дочерний элемент будет расположен в ячейке сетки. Допустимые значения - start, end, center и stretch (по умолчанию).
  • -ms-grid-column-span и -ms-grid-row-span показывает, будет ли дочерний элемент занимать одну строку и один столбец, или же несколько.
  • -ms-grid-layer управляет тем, как элементы сетки перекрываются. Это похоже на стиль z-index, используемый для элементов, которые можно позиционировать. Так как дочерние элементы сетки не позиционируются напрямую из CSS, позиционируясь, вместо этого, в соответствии с сеткой, -ms-grid-layer позволяет управлять этим.
  • Обратите особое внимание на то, что нумерация строк и столбцов начинается с 1, а не с 0. Перепрограммируйте ваш ум, ориентированный на JavaScript для того, чтобы это запомнить, так как вам понадобится небольшая трансляция адресов в том случае, если вы храните дочерние элементы в массиве, нумерация которого начинается с 0.

    Кроме того, обращаясь к любому из этих -ms-grid* стилей как к свойствам в JavaScript, опустите тире и переключитесь на написание адресов в "верблюжьем" (camel casing) стиле: msGrid, msGridColumns, msGridRowAlign, msGridLayer.

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

    Переполнение ячейки сетки

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

    Пример содержимого, которое выступает за пределы содержащей его ячейки можно найти в упражнении GridOverflow в дополнительных материалах к этой лекции. Здесь создана сетка из прямоугольных элементов, 4х4, но нижеприведенный код, размещенный в конце функции doLayout (js/default.js) размещает первый прямоугольник за пределами ячейки:

    children[0].style.width = "350px"; children[0].style.marginLeft = "150px"; children[0].style.background = "#fbb";

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

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

    Вертикальная центровка содержимого

    Где-то, в собственном опыте работы с CSS вы, возможно, сталкивались с неприятным поведением стиля vertical-align в попытке разместить фрагмент текста в центре или в нижней части элемента div. К несчастью, это не работает: этот стиль предназначен для ячеек таблицы и для встроенного содержимого (для того, чтобы задать, как текст и изображения, например, выравниваются относительно друг друга).

    В результате, для того, чтобы это реализовать, было разработано множество методов. Например, об этом идет речь здесь: http://blog.themeforest.net/tutorials/vertical-centering-with-css/. К несчастью, практически все эти методы основаны на фиксированной высоте - а это может работать для веб-сайта, но не подходит для адаптивных макетов, в которых нуждаются приложения для Магазина Windows. И единственный метод, который не использует фиксированную высоту, основан на применении встраиваемой таблицы. Эх.

    К счастью, и CSS-сетка, и гибкое окно (смотрите раздел "Макет элемента" ниже) позволяют легко решить эту проблему. В случае с сеткой, вы можете просто создать родительский элемент div с сеткой 1х1 и использовать стиль -ms-grid-row-align: center для дочернего элемента div (значение по умолчанию для которого - ячейка 1,1):

    <!-- В HTML -->	
    <div id="divMain">	
    <div id="divChild">	
    <p>Centered Text</p>
    </div>	
    </div>
    
    /* В CSS */
    #divMain { width: 100%; height: 100%; display: -ms-grid;
    -ms-grid-rows: 1fr;
    -ms-grid-columns: 1fr;
    }
    
    #divChild {
    -ms-grid-row-align: center;
    -ms-grid-column-align: center;
    
    /* Горизонтальное выравнивание текста так же работает с */
    /* text-align: center; */	
     }

    Решение этой проблемы даже проще с помощью макета на основе flexbox, где flex-align: center задаёт вертикальную центровку, flex-pack: center отвечает за горизонтальную центровку, и дочерний элемент div не нужен. Это тот же подход к стилизации, что применен в шаблоне Приложение с фиксированным макетом для центровки элемента ViewBox:

    <!-- В HTML -->	
    <div id="divMain">	
    <p>Centered Text</p>
    </div>	
    /* В CSS */
    #divMain { 
    width: 100%; height: 100%;
    display: -ms-flexbox;
    -ms-flex-align: center;
    -ms-flex-direction: column;
    -ms-flex-pack: center;
    }

    Код обоих методов можно найти в упражнении CenteredText к этой лекции. (Упражнение так же используется для демонстрации применения многоточий, в итоге он выглядит не точно так же, как показано выше).

    Масштабирование размеров шрифтов

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

    При работе с адаптивным макетом, обычно нужно, чтобы размер шрифта был пропорционален размерностям его родительского элемента. (Это не проблема, если родительский элемент имеет фиксированный размер, потому что так вы можете использовать шрифт фиксированного размера). К несчастью, процентные значения, используемые в стиле font-size в CSS, основаны на размере шрифта по умолчанию (1em), а не на размере родительского элемента, как в случае с height и width. Вам, вероятно, понравилось бы использование выражения наподобие font-size: calc(height * .4), но значения других CSS-стилей того же самого элемнта не доступны calc.

    Одно исключение из этого правила касается значения vh (которое можно использовать в calc). Если вы знаете, например, что текст, который вы хотите масштабировать, содержится в ячейке сетки, которая всегда занимает 10% от высоты окна вывода, и вы хотели бы, чтобы размер шрифта равнялся половине от этого значения, вы можете воспользоваться выражением font-size: 5vh (5% от высоты окна просмотра).

    Другой метод заключается в использовании SVG для вывода текста, где вы можете установить атрибут viewBox и задать font-size относительно этого viewBox. Затем, масштабирование SVG по отношению к ячейке сетки эффективно масштабирует и шрифт:

    <svg viewBox="0 0 600 400" preserveAspectRatio="xMaxYMax">
    <text x="0" y="150" font-size="200" font-family="Verdana"> Big SVG Text
    </text>
    </svg>

    Так же вы можете воспользоваться JavaScript для вычисления желаемого размера шрифта, основываясь на свойстве clientHeight родительского элемента. Если данный элемент находится в ячейке сетки, размер шрифта (и высотра строки) могут составить некоторый процент от высоты ячейки, таким образом, позволяя масштабировать шрифт вместе с ячейкой.

    Так же вы можете попытаться использовать элемент управления WinJS.UI.ViewBox. Если вам нужно, чтобы текст занял 50% элемента, содержащего его, поместите ViewBox в div, который настроен на размер, равняющийся 50% размера контейнера, и стилизуйте дочерний элемент элемента ViewBox с помощью position: absolute. Попытайтесь, для того, чтобы увидеть это, поместить нижеприведеннй код в default.html нового проекта, созданного на основе шаблона Пустое приложение:

    <div style="height:50%;">	
    <div data-win-control="WinJS.UI.ViewBox">	
    <p style="position:absolute;">Big text!</p>
    </div>	
    </div>

    Макет элемента

    До сих пор в этой лекции мы исследовали макеты уровня страницы, которые определяют то, как элементы верхнего уровня расположены на странице, обычно - с помощью CSS-сетки. Конечно, всё это - лишь HTML и CSS, поэтому вы можете использовать таблицы, разрывы строк и всё, что поддерживается подсистемой рендеринга, если это позволяет вам создавать макеты, подходящие для разных режимов просмотра и размеров дисплея.

    Важна и работа с шаблонами отдельных элементов, которые расположены в изменяющихся областях страницы. Таким образом, если вы задали сетку, определяющую общий вид страницы и получили с её помощью некоторое количество областей фиксированного размера (для заголовков, изображений в заголовке, панелей управления и так далее), оставшаяся область может сильно меняться в размере при изменении размеров окна. В этом разделе, таким образом, давайте взглянем на некоторые средства, которые мы можем применять в подобных областях: CSS-трансформации, гибкое окно, вложенные и встроенные сетки, многоколоночный текст, CSS-выражения и объединенные CSS-рамки. Информацию по этим и другим возможностям CSS, которые поддерживаются приложениями для Магазина Windows (такие, как фоны, границы, градиенты), можно найти в материале "Каскадные таблицы стилей" (http://msdn.microsoft.com/library/windows/apps/hh996828.aspx).

    2D и 3D-трансформации в CSS

    Практически невозможно размышлять о макетах для элементов не принимая во внимание CSS-трансформации. Трансформации - очень мощное средство, так как они делают возможным изменение отображения элемента, не воздействуя ни на последовательность элементов в документе, ни на общий макет. Это очень полезно для реализации анимаций и переходов. Трансформации широко используются библиотекой анимации WinJS, которые обеспечивают внешний вид и восприятие встроенных элементов управления, характерные для Windows 8. Как мы узнаем в лекции 5 курса "Пользовательский интерфейс приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript", вы можете так же напрямую пользоваться этой библиотекой.

    CSS-трансформации можно использовать непосредственно, конечно, в любое время, когда вам нужно преобразовать, масштабировать, повернуть элемент. Приложения для Магазина Windows поддерживают и 2D (двумерные) и 3D (трехмерные) трансформации (http://dev.w3.org/csswg/css3-2d-transforms/Во время написания этого материала префиксы -ms-* для данных стилей уже не нужны, но всё еще поддерживаются.:

    CSS-стильСвойство JavaScript (element.style.)
    backface-visibilitybackfaceVisibility
    perspective, perspective-origin perspective, perspectiveOrigin
    transform, transform-origin, и transform-styletransform, transformOrigin, и transformStyle

    Подробности можно найти на странице "Трансформации" (http://msdn.microsoft.com/library/windows/apps/hh453377.aspx). Знайте так же, что так как хост-процесс приложения использует те же механизмы, что и Internet Explorer, трансформации используют все преимущества аппаратного ускорения.

    Гибкое окно (flexbox)

    Так же, как сетка - отличный инструмент для решения проблем макетов страниц, модуль гибкое окно CSS, описанный в http://www.w3.org/TR/css3-flexbox/, прекрасно подходит для работы с областями, размеры которых могут меняться, содержимое в которых нуждается в "заполнении" доступного пространства. Процититуем спецификацию W3C:

    В данной оконной модели, дочерние элементы окна размещаются либо горизонтально, либо вертикально, неиспользованное пространство может быть назначено конкретным дочерним элементом или распределено между такими элементами путём назначения 'flex' тем дочерним элементам, которые должны заполнять это пространство. Вложенность подобных окон (горизонтальное внутри вертикалного, или вертикальное внутри горизонтального) может быть использована для построения двумерных макетов.

    Так как спецификации гибкого окна представлены в форме чернового стандарта, конкретные стили, используемые в приложениях для Магазина Windows - это Если вы привыкли к стилям -ms-box* для гибких окон, Microsoft с тех пор следует спецификациям W3C, где ожидается последняя старшая редакция перед финальным принятием стандарта. Когда новый синтаксис заменит старый, старый не будет работать ни в приложениях для Магазина Windows, ни в Internet Explorer 10.. Полную справочную информацию по другим поддерживаемым свойствам вы можете найти на странице "Макет на основе гибкого окна ("Flexbox")" (http://msdn.microsoft.com/library/windows/apps/hh453474.aspx):

    CSS-стильСвойство JavaScript (element.style.)Значения
    -ms-flex-align msFlexAlign start | end | center | baseline | stretch
    -ms-flex-direction msFlexDirection row | column | row-reverse | column-reverse | inherit
    -ms-flex-flow msFlexFlow <direction> <pack> где <direction> это значение -ms-flex-direction и <pack> это значение -ms-flex-pack
    -ms-flex-orientmsFlexOrienthorizontal | vertical | inline-axis | block-axis | inherit
    -ms-flex-item-align msFlexItemAlign auto | start | end | center | baseline | stretch
    -ms-flex-line-pack msFlexLinePack start | end | center | justify | distribute | stretch
    -ms-flex-order msFlexOrder <integer> (порядковый номер группы)
    -ms-flex-pack msFlexPack start | end | center | justify
    -ms-flex-wrap msFlexWrap none | wrap | wrapreverse

    Как и для всех остальных стилей, Blend - это отличный инструмент, с помощью которого можно экспериментировать с различными стилями гибких окон, так как вы можете сразу же видеть эффект от их применения. Также полезно знать, что гибкое окно используется во многих местах WinJS и в шаблонах проектов, как мы видели ранее в случае с шаблоном Приложение с фиксированным макетом. В частности, возможности гибкого окна использует элемент управления ListView, это позволяет ему отображать больше элементов, когда доступно больше пространства. Элемент управления FlipView использует гибкое окно для центровки элементов. Элементы управления Ratings, DataPicker и TimePicker организуют свои внутренние элементы с использованием встроенного гибкого окна. Весьма вероятно, что ваши собственные пользовательские элементы управления будут поступать так же.

    Вложенные и встроенные сетки

    Так же, как и гибкое окно имеет модели блочного уровня и встроенные модели, существуют и встроенные сетки: display: -ms-inline-grid. В отличе от сетки блочного уровня, встроенный вариант позволяет вам располагать несколько сеток на одной и той же линии. Это показано в упражнении InlineGrid, где у нас есть три элемента div в HTML, которые можно переключать между встроенной моделью (по умолчанию) и моделью блочного уровня:

    //В обработчике activated	
    document.getElementById("chkInline").addEventListener("click", function () {
    setGridStyle(document.getElementById("chkInline").checked);	
    });	
    setGridStyle(true);
    
    //В любом месте в default.js 
    function setGridStyle(inline) {
    var gridClass = inline ? "inline" : "block";
    
    document.getElementById("grid1").className = gridClass;
    document.getElementById("grid2").className = gridClass;
    document.getElementById("grid3").className = gridClass;
    }	
    
    /* default.css */	
    .inline {	
    display: -ms-inline-grid;
    }	
    
    .block {
    display: -ms-grid;
    }

    При использовании встроенной сетки элементы выглядят так:

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

    Шрифты и переполнение текстом

    Как упоминалось ранее, типографика - это важный элемент дизайна приложений для Магазина Windows, и, в основном, стандартные стили шрифтов, использующие Segoe UI, уже заданы в таблицах стилей WinJS. В Windows SDK есть очень полезный пример "CSS-типографика" (http://code.msdn.microsoft.com/windowsapps/typography-JS-sample-e2df9eb4), где сравнивается элементы заголовков HTML и стили win-type-*, показывая запасные варианты шрифтов и использование двунаправленных шрифтов (с направлением слева направо и справа налево).

    Если говорить о шрифтах, пользовательские шрифтовые ресурсы, использующие правило @font-face в CSS, разрешены в приложениях для Магазина Windows. Для страниц локального контекста, свойство src правила должно ссылаться на шрифт файла, который находится в пакете (то есть, это URI, который начинается с / или с ms-appx:///). Страницы, исполняющиеся в веб-контексте, могут загружать шрифты из удалённых источников. Другой вопрос, касающийся текстов и типографики касается текста, который выходит за пределы выделенной для него области. Вы можете использовать стиль CSS text-overflow: ellipsis; для обрезки текста и добавления в конец текста …, и таблицы стилей WinJS содержат класс win-type-ellipsis для этих целей. В дополнение к установке text-overflow, этот класс так же добавляет overflow: hidden (для подавления появления полос прокрутки), и white-space: nowrap. Эти стили вы можете добавлять к любому текстовому элементу, когда вы хотите реализовать поведение, касающееся усечения текста.

    Спецификация W3C, касающася переполнения текстом, http://dev.w3.org/csswg/css3-ui/#text-overflow, содержит полезные сведения о том, что можно и что нельзя сделать в этой области. Одно из ограничений текущей спецификации заключается в том, что многострочный обтекающий текст не работает с усечением текста. Таким образом, вы можете использовать обтекание текстом с помощью стиля word-wrap: breakpword, но не можете совместить его с text-overflow: ellipsis (word-wrap имеет преимущество). Я так же узнал, что перетекающий текст из многострочной CSS-области (смотрите следующий раздел) работает в однострочной области с возможностью усечения текста, но text-overflow не применим к областям. В итоге, сейчас вы нуждаетесь в сокращении текста и ручной вставке многоточий, если текст занимает несколько строк.

    Для демонстрации сокращения текста и обтекания словами, посмотрите упражнение к этой лекции CenteredText.

    Многоколоночные элементы и области

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

    CSS3 предоставляет средства для создания многоколоночных макетов внутри элемента (смотрите http://www.w3.org/TR/css3-multicol/). С помощью этих средств вы можете настроить отдельный элемент так, чтобы он расположил своё содержимое в несколько колонок и указать множество параметров подобного макета. Соответствующие стили поддерживают и приложения для Магазина Windows (без необходимости использования префиксов поставщика):

    CSS-стилиСвойство JavaScript (element.style.)
    column-width и column-count (columns это сокращение) columnWidth, columnCount, и columns
    column-gap, column-fill, и column-span columnGap, columnFill, и columnSpan
    column-rule-color, column-rule-style, и columnRuleColor, columnRuleStyle, и columnRuleWidth
    column-rule-width (column-rule это сокращение для разделителей колонок)(columnRule это сокращение)
    break-before, break-inside, и break-after breakBefore, breakInside, и breakAfter
    overflow: scroll (для отображения в контейнере полос прокрутки) overflow

    Соответствующую документацию можно найти на странице "Многоколоночный макет" (http://msdn.microsoft.com/library/windows/apps/hh441204.aspx).

    Blend предоставляет отличное окружение для того, чтобы увидеть, как работают эти стили. Если вы размещаете мнокоголоночный элемент внутри ячейки сетки, которая может менять размер, вы можете задать параметр column-width и позволить подсистеме макетов добавлять и удалять колонки при необходимости, или вы можете использовать медиа-запросы или JavaScript для самостоятельной установки свойства column-count.

    Многоколоночная верстка CSS3, опять же, может быть применена лишь к содержимому одного отдельного элемента. Будучи весьма полезной, она имеет ограничения на использование прямоугольных элементов-контейнеров и прямоугольных колонок (увеличение их числа происходит в бок). Определенные приложения, наподобие электронных журналов, нуждаются в большей гибкости, в такой, как перетекание содержимого между несколькими элементами с более разнообразной формой, и в колонках, которые имеют смещение относительно друг друга. Эти взаимоотношения показаны на Рис. 6.8, где прямоугольник в левой верхней части может быть заголовком, блок-вставка может содержать изображение, и текстовое содержимое распределено между двумя колонками неправильной формы.

    (рис 6.8) Использование областей CSS для создания более сложных макетов с текстовыми колонками неправильной формы

    Для поддержки колонок неправильной формы, области CSS (CSS Regions) (http://dev.w3.org/csswg/css3-regions/) приходят в онлайн и поддерживаются приложениями для Магазина Windows (смотрите материал "Области" (http://msdn.microsoft.com/library/windows/apps/hh453722.aspx)). Области позволяют произвольно (это так - абсолютно) позиционировать элементы для взаимодействия со встроенным содержимым. На Рис. 6.8 изображение может быть позиционировано с использованием абсолютных параметров на странице и содержимое колонок будет его обтекать.

    Ключевый стиль для позиционирования элемента это float: -ms-positioned, который следует сопровождать position: absolute. Обычно это всё, что вам нужно: разместить в нужном месте позиционированный элемент, а подсистема макета сделает всё остальне. Следует отметить, что CSS-перенос (Hyphenation), еще один модуль, близко связан со всем этим, так как выполняет динамическое макетирование текста, мгновенно предоставляя подобные возможности. К счастью, приложения для Магазина Windows поддерживают -ms-hyphens и стили -ms-hyphenation* (их эквивалентные им свойства JavaScript). Переносы описаны в http://www.w3.org/TR/css3-text/, документацию, относящуюся к приложениям для Магазина Windows можно найти в материале "Области" (http://msdn.microsoft.com/library/windows/apps/hh453722.aspx).

    Вторая часть рассказа касается так называемых цепочек потоков или областей (которые, так же, являются частью спецификации, касающейся областей). Они обеспечивают возможность перетекания содержимого между множеством элементов-контейнеров, как показано на Рис. 6.9. Цепочки областей могут так же позволить стилизовать содержимое в соответствии со стилем контейнера, вместо того, чтобы стилизовать их так, как задано в их источнике. Каждый контейнер, другими словами, может задать собственный стиль и содержимое адаптируется к нему, но обычно, для обеспечения единообразия, все контейнеры имеют похожие стили.

    (рис 6.9) Цепочка CSS-областей позволяет содержимому перетекать между множеством элементов

    Всё это работает следующим образом. Источник контента определяет элемент iframe, который указывает на HTML-файл (и iframe, конечно, может принадлежать и локальному и веб-контексту). Он стилизуется с помощью ms-flow-into: <element> (в JavaScript - msFlowInfo), где <element> - это id первого контейнера:

    <!-- HTML -->	
    <iframe id="s1-content-source" src="/html/content.html"></iframe>
    <div class="s1-container"></div>	
    <div class="s1-container"></div>	
    <div class="s1-container"></div>	
    
    /* CSS */
    #s1-content-source {
    -ms-flow-into: content;
    }

    Обратите внимание на то, что -ms-flow-into предотвращает отображение содержимого лишь в iframe.

    Контейнером может быть любой незаменяемый (nonreplaced) элемент. То есть, любой элемент, внешний вид и размеры которого не определяются внешним источником, такой, как img. Он должен поддерживать включение содержимого между его открывающим и закрывающим тегами, наподобие div (он используется чаще всего), или p. Каждый контейнер стилизуется с помощью -ms-flow-from: <element> (msFlowFrom в JavaScript), где <element> - это первый контейнер в потоке. Расположение содержимого затем производится в том порядке, в котором элементы появляются в HTML (как выше):

    .s1-container {
    -ms-flow-from: content;
    /* Другие стили */
    }

    Этот простой пример взят из примера "Статические области CSS" (http://code.msdn.microsoft.com/windowsapps/Static-Regions-sample-f2158049), который так же содержит несколько других сценариев. Есть еще два интересных проекта, пример "Динамические области CSS" (http://code.msdn.microsoft.com/windowsapps/Dynamic-Region-Templates-94bc9c95), и "Шаблоны динамических областей CSS" (http://code.msdn.microsoft.com/windowsapps/Dynamic-Region-Templates-94bc9c95), последний является источником рисунка 6.8. Во всех этих случаях знайте, что стилизация областей ограничена свойствами, которые воздействуют на контейнер, но не на содержимое. Стиль содержимого взят из HTML-источника iframe. Именно поэтому text-overflow: ellipsis не работает, так же не работает font-color и так далее. Но стили, наподобие height и width, вместе со стилями границ, полей, отступов и другие свойства, которые не влияют на содержимое, применять можно.

    Что мы только что изучили

  • Макеты, которые соответствуют принципам дизайна Windows 8, а в особенности - общему стилю и типографике - помогают пользователям без промедления концентрироваться на содержимом вместо того, чтобы заниматься изучением особенностей приложений.
  • Принцип "прежде всего содержимое, и лишь затем внешнее оформление" позволяет содержимому использовать 75% пространства дисплея или даже больше, вместо 25%, что обычно для настольных и веб-приложений, уделяющих большое внимание внешнему оформлению.
  • В некоторых случаях, в таких, как создание домашней страницы или хаба приложения с различным содержимым, не поступающим из какой-то одной коллекции, лучше использовать обычный HTML/CSS макет вместо использования элемента управления.
  • Сдвигаемые HTML-области могут использовать точки прикрепления для автоматической остановки сдвига на определенных позициях внутри содержимого.
  • CSS-сетка - это весьма удобный механизм для создания адаптивных макетов уровня страницы, его можно использовать и во встроенном варианте. Гибкое окно CSS особенно удобно для встроенного содержимого, хотя его можно использовать и на уровне страницы, например, для центровки содержимого горизонтально и вертикально.
  • Каждая страница приложения (включая расширенный экран-заставку) может встретиться со всеми четырьмя режимами просмотра, поэтому дизайн приложения должен показывать, как обрабатываются все эти состояния. Медиа-запросы и API Media Query Listener можно использовать для обработки изменений состояния просмотра как декларативно, так и программно.
  • Приложения могут задавать предпочтительную ориентацию в манифесте и блокировать смену ориентации во время выполнения.
  • Событие window.onresize лучше всего позволяет узнать, когда изменился размер окна, что может быть обусловлено изменением состояния просмотра и/или изменением размера экрана и плотности пикселей.
  • Поддержка различных размеров экрана реализуется посредством адаптивных макетов, основанных на сетке или фиксированных макетов, использующих элемент управления WinJS.UI.ViewBox, который выполняет автоматическое масштабирование своего содержимого.
  • Основное условие, касающееся работы с экранами, поддерживающими различную плотность пикселей, заключается в использовании графических элементов, которые хорошо масштабируются. Это означает либо использование векторных изображений, либо предоставление масштабированных вариантов каждого из растровых изображений.
  • Приложения для Магазина Windows могут использовать возможности большого количества средств CSS, в том числе - сетки, гибкого окна, трансформации, многоколоночного текста и областей.
  • Страницы:

    Файлы к данной лекции Вы можете скачать здесь.

    В сравнении с другими членами моей семьи, я меньше сплю и часто встаю поздно ночью или перед рассветом. Для того, чтобы не будить остальных, я обычно не включаю свет и перемещаюсь в темноте (здесь, в сельских предгорьях Сьерра-Невады, бывает по-настоящему темно!) Так как я знаю планировку дома и расстановку мебели, мне не нужно многого видеть. Я лишь нуждаюсь в нескольких контрольных точках, вроде дверного проёма, углов стен или края кровати, для того, чтобы точно знать, где я нахожусь. Более того, моё тело обладает мышечной памятью, в которой зафиксировано расположение дверных ручек, количество ступенек на лестнице, количество шагов, необходимое, чтобы обойти кровать и так далее. Это по-настоящему помогло мне понять, как слабовидящие люди "видят" их мир.

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

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

    Хороший дизайн приложения, очевидно, следует тем же принципам. Именно поэтому Microsoft рекомендует следовать единообразным шаблонам поведения приложений, как описано в материалах "Разработка интерфейсов пользователя для приложений" (лекции 1 курса "Пользовательский интерфейс приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript"), продиктованы особенностями анатомии людей, а именно, тому, как далеко мы можем перемещать пальцы по экрану, удерживая при этом в руках планшетный компьютер.

    В случае с макетами страниц, рекомендации, "Создание макета приложения" (http://msdn.microsoft.com/library/windows/apps/hh872191.aspx), где показано идеальное расположение тела страницы и заголовков, где выверены расстояния между элементами страницы, могут показаться серьезно ограничивающими ваши возможности, если не драконовскими. Общий стиль Windows, однако - это отличная отправная точка, но не жёсткое правило. Гораздо важнее, что форма макета приложения помогает пользователям развивать визуальную и мышечную память, которая применима ко многим приложениям. Исследования показали, что пользователь вырабатывает подобные привычки довольно быстро, за минуты. Но, конечно, эти привычки не имеют попиксельной точности. Другими словами, общий стиль показывает общую форму, которая помогает пользователю немедленно понять, как работает приложение и где нужно искать определенные его функции. Это похоже на то, как вы легко узнаете букву "S", набранную разными шрифтами. Такой подход эффективен и продуктивен. С другой стороны, когда существует приложение, которые использует совершенно иной макет (или, что хуже, когда макет похож на макет в стиле Windows 8, а работает он иначе), пользователь может потратить больше сил на то, чтобы понять, куда посмотреть, куда кликнуть, так же, как я вынужден был бы быть гораздо более внимательным ночью, если бы вы передвинули всю мою мебель!

    Суть заключается в том, что за всеми рекомендациями по проектированию приложений для Магазина Windows лежат веские причины. Как я сказал раньше, если вы выполняете роль дизайнера своего приложения, изучите те руководства, ссылки на которые приведены выше. Если эту роль взял на себя кто-то другой, убедитесь в том, что он изучил эти руководства! В любом случае, мы рассмотрим основные принципы в первом разделе данной лекции.

    После этого мы скоцентрируемся на том, как реализовать дизайн макета, а не на создании дизайна как такового. (Хотя я, очевидно, унаследовал от моих родителей гены, которые наградили меня способностями к технической коммуникации, мой брат получил больше генов, которые в ответе за искусство!). Например, мы ответим на вопросы о том, как приложение должно отвечать на изменение режима просмотра для того, чтобы показать страницы в правильном дизайне (для полноэкранного альбомного, заполняющего, прикрепленного, портретного режимов)? Как приложение ведет себя на экранах различных размеров и различной плотности пикселей?

    Кроме того, мы потратим некоторое время на работу с CSS-сеткой и некоторыми другими возможностями CSS, имеющими отношение к макетам, такими, как гибкие окна или многоколоночный текст. Вообще говоря, всё это - стандарты CSS, поэтому я ожидаю, что вы уже знаете что-то о них, или можете разыскать полную документацию по нимТехническую документацию можно найти по адресу: http://www.w3c.org; а именно, начните с http://www.w3.org/standards/webdesign/htmlcss и для HTML и для CSS. Кроме того, я горячо рекомендую отлично спроектированные и находящиеся под наблюдением ресурсы из Smashing Magazine для изучения нюансов CSS, которые, должен признать, время от времени кажутся мне весьма таинственными.. Мы, таким образом, рассмотрим лишь некоторые основы, потратив больше времени на то, чтобы понять, как лучше всего применять эти возможности в приложениях, и на аспекты, уникальные для среды Windows 8 (на то, например, что называется точкой прикрепления (snap point) в элементе div, поддерживающем сдвиг / прокрутку (pan / scroll)).

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

    Принципы построения макетов приложений для Магазина Windows

    Макет, очевидно, является одним из центральных элементов, которого касаются рекомендации по дизайну приложений для Windows. Принцип "прежде всего содержимое, и лишь затем внешнее оформление" ("content before chrome") означает, что большая часть того, что вы отображаете на каждой из страниц приложения - это содержимое, с небольшим количеством управляющих поверхностей, постоянных навигационных панелей и пассивных графических элементов наподобие разделителей, размытий, градиентов, которые сами по себе ничего не значат. Другой вариант реализации подобного заключается в том, что содержимое само по себе следует сделать интерактивным, вместо того, чтобы конструкировать пассивные элементы, управляющее воздействие на которые оказывают команды, активируемые пользователем не посредством самих этих элементов. Семантическое масштабирование - хороший пример подобного интерактивного содержимого - вместо необходимости иметь кнопки или меню для изменения масштаба где-то в приложении, эту возможность реализует сам элемент управления, иногда, когда с приложением работают с помощью мыши, выводя небольшую кнопку зуммирования. Другие команды приложения, по большей части, похожим образом привязаны к элементам пользовательского интерфейса, которые появляются тогда, когда они нужны, посредством панелей приложения и других всплывающих элементов, о которых мы поговорим в лекции 1 курса "Пользовательский интерфейс приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript".

    Коротко говоря, принцип "прежде всего содержимое, и лишь затем внешнее оформление" подразумевает создание эффекта погружения в содержимое для пользователя, работающего с приложением, вместо того, чтобы отвлекать его на несущественные детали. В проектировании приложений для Магазина Windows особое внимание уделяется пустому пространству вокруг содержимого и между отдельными его блоками, которое служит для организации и группировки содержимого без необходимости в линиях и рамках. Обычно прозрачные "рамки из пустого пространства" помогают взгляду пользователя притягиваться к содержимому, которое имеет значение. В дизайне приложений для Windows используются принципы типографики (размер шрифта, его насыщенность, цвет и так далее) для создания ощущения структуры, иерархии и сравнительной важности различного содержимого. Это так по той причине, что текст на странице - это уже содержимое, почему бы не использовать его характеристики - типографику - для того чтобы достичь тех же целей, которые обычно достигаются за счёт внешних элементов оформления? (Если говорить об общем стиле макета, широкое использование шрифта Segoe UI в дизайне приложения не является жёстким правилом, скорее начальной точкой. Применение однородных наборов параметров шрифтов (type ramp) для различных заголовков важнее, нежели сами шрифты).

    В качестве примера, на Рис. 6.1 показан типичный дизайн настольного или веб-приложения для чтения RSS-лент. Обратите внимание на постоянные элементы внешнего оформления сверху и снизу: команда поиска, закладки для навигации, элементы управления для навигации и так далее. Это занимает примерно 20% пространства экрана. В том, что остаётся примерно две трети занимают служебные элементы, оставляя лишь 20-25% на содержимое, которое нам действительно нужно - на статью.

    Рис. 6.2 показывает приложение для тех же целей, дизайн которого соответствует дизайну для Магазина Windows. Обратите внимание на то, как вспомогательные команды убраны с основного экрана. Поиск можно выпонить с помощью чудо-кнопки Поиск. Настроить параметры можно посредством чудо-кнопки Параметры. Добавление новых лент, обновление, навигация - реализованы на панели приложения. А переключение между режимами просмотра реализовано на основе контекстного масштабирования. Для отражения иерархии содержимого используется типографика вместо элементов управления, изображающих папки. В итоге, для содержимого доступна большая часть экрана - около 75%. В результате, мы можем увидеть гораздо больше содержимого, чем раньше, что создаёт гораздо более глубокий и захватывающий опыт взаимодействия пользователя и приложения. Не так ли?

    (рис 6.1) Дизайн типичного настольного или веб-приложения, основанный на элементах оформления, которые отображаются за счет полезного содержимого (рис 6.2) То же самое приложение, что и на Рис. 6.1., преображенное с использованием нового подхода к дизайну Windows-приложений, где большая часть элементов оформления исчезает, оставляя гораздо больше места для содержимого. В альтернативном варианте такого дизайна изображения могут выделяться сильнее, чем текст

    Даже там, где применяются правила типографики, дизайн для Windows приветствует использование различных размеров шрифта, набора типографских параметров, для того, чтобы создать ощущение иерархии. Таблиц стилей WinJS по умолчанию - ui-light.css и ui-dark.css - предоставляют четыре фиксированных размеров шрифта, где каждый следующий уровень пропорционально больше предыдущего (42 пункта = 80 пикселей, 20 пунктов = 40 пикселей и так далее, как показано на Рис. 6.3. Эти пропорции позволяют пользователю легко, с одного взгляда, выяснять и понимать структуру содержимого. Опять же, это касается привычек и мышечной памяти, и исследования Microsoft показали, что без подобной разницы в размерах, пользователь обычно не может чётко определить роль того или иного содержимого в общей иерархии.

    (рис 6.3) Набор типографских параметров в дизайне приложений для Магазина Windows, показанный для таблиц стилей ui-light.css (слева) и ui-dark.css (справа)

    Внутри основного содержимого дизайн для Windows приветствует следующие принципы построения макетов:

  • Позвольте содержимому располагаться от края до края.
  • Помните об эргономике: осуществляйте сдвиг содержимого вдоль длинного края области просмотра (обычно горизонтального в альбомном режиме, вертикального - в прикрепленном, и, возможно, в портретном).
  • Осуществляйте сдвиг содержимого только по одной оси, что создаёт ощущение стабильности и позволяет использовать жест скольжения по диагонали для выделения (как в случае с элементом управления ListView), или используйте ограничители (rails) для ограничения направления сдвига одной осью.
  • Выравнивайте содержимое, создавайте структуру, чёткость, следуя общему стилю Windows 8, выравнивая элементы по сетке для их единообразного расположения. Обратитесь снова к материалу "Создание макета приложения" (http://msdn.microsoft.com/library/windows/apps/hh872191.aspx). Здесь показано, что позволяет глазам пользователя принимать что-то за приложение для Магазина Windows без необходимости размышлять об этом, что создаёт ощущение того, что пользователь знаком с приложением и чувствует себя в нём уверенно.
  • Как мы упоминали выше, шаблоны проектов в Visual Studio и Blend созданы с учётом этих принципов, и, таким образом, предоставляют удобную стартовую точку для приложений. Даже если вы начинаете с шаблона Пустое приложение, другие, наподобние шаблона Приложение таблицы, будут служить справочным материалом. Именно это мы сделали с приложением "Here My Am!" в лекции 2.

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

    Быстрый старт: Сдвигаемые разделы и точки прикрепления

    В лекции 5 мы потратили некоторое время на разговор о том, когда ListView - это правильный выбор, а когда - нет. Один из главных случаев, когда разработчики неоправданно пытаются использовать ListView, заключается в реализации домашней страницы или хаба приложения, который содержит множество различных групп содержимого, организованных в столбцы, как показано на Рис. 6.4 и разъяснено в материале "Проектирование навигации для приложений Магазина Windows" (http://msdn.microsoft.com/library/windows/apps/hh761500.aspx). На первый взгляд это выгдялит как ListView, но так как данные, на самом деле, не являются коллекцией, это лишь макет, выводящий фиксированное содержимое, в итоге, имеет смысл использовать для подобной работы HTML и CSS, через метод проб и ошибок.

    Я особо обратил на это ваше внимание, так как все отличные элементы управления, которые предоставляет WinJS, позволяют просто забыть о том, что всё, что вы знаете об HTML и CSS, всё еще применимо в приложениях для Магазина Windows. В конце концов, эти элементы управления - лишь блоки HTML и CSS с некоторыми дополнительными методами, свойствами и событиями.

    (рис 6.4) Макет типичной домашней страницы (хаба) приложения для Магазина Windows с фиксированным заголовком (1) и горазонтально сдвигаемым разделом (2), и разделами или категориями содержимого (3)

    Создание макета хаба

    Посмотрим, как использовать HTML и CSS для того, чтобы реализовать раздел стартовой страницы приложения (хаба), который поддерживает сдвиг, как на Рис. 6.4. Вспомнив, для начала, к материалу "Создание макета приложения" (http://msdn.microsoft.com/library/windows/apps/hh872191.aspx), мы можем сказать, что отступ между группами должен составлять четыре единицы по 20 пикселей каждая, то есть - 80 пикселей. Большинству групп следует иметь квадратную форму, за исключением второй, ширина которой вдвое меньше. Основываясь на размерах дисплея, 1366х768, высота каждого раздела должна составлять 768 пикселей минус 128 пикселей (это место для заголовка), минус, как минимум, 50 пикселей снизу. В итоге остаётся 590 пикселей (если мы добаим заголовки групп для каждого раздела, нужно будет вычесть еще 40 пикселей). В итоге, квадратная группа на базовом дисплее будет иметь 590 пикселей в ширину (мы установили реальную высоту в 100% содержащей её ячейки сетки). Полная ширина раздела будет, таким образом, (590*4 полноразмерных раздела)+(295*один раздел половинной ширины)+(80*4 разделительные пустые пространства). Результат равняется 2975 пикселей. К этому мы добавим колонки по краям - 120 пикселей слева (в соовтетствии с общим стилем Windows) и 80 пикселей справа. В итоге, мы получаем 3175 пикселей.

    Для того, чтобы создать раздел с подобным макетом, мы можем использовать CSS-сетку внутри элемента-контейнера. Для того, чтобы это увидеть, запустим Blend, создадим новый проект с шаблоном Приложение навигации (у нас будет базовая страница, но не все вспомогательные страницы, всё будет оформлено в нужном стиле). Внутри элемента section в pages/home/home.html, создадим новый div-элемент и зададим его параметр класс как hubSections:

    <section aria-label="Main content" role="main">
    <div class="hubSections">	
    </div>	
    </section>

    По адресу pages/home/home.css добавим несоколько правил стилей. Зададим параметр overflow-x: auto элементу section, и расположим сетку в div'е hubSections, используем добавление колонок слева и справа для создания отступов (удалив margin-left: 120px из section и добавив это в качестве первого столбца в div):

    .homepage section[role=main] {
    overflow-x: auto;
    }
    .homepage .hubSections { 
    width: 2975px; 
    height: 100%; 
    display: -ms-grid;
    -ms-grid-rows: 1fr 50px;
    -ms-grid-columns: 120px 2fr 80px 1fr 80px 2fr 80px 2fr 80px 2fr 80px;
    }

    Применив эти стили, мы уже можем увидеть, как начальная страница принимает форму, уменьшив масштаб отображения данных на монтажной панели:

    Теперь создадим отдельные разделы в pages/home/home.html, каждый из них представляет собой div.

    <section aria-label="Main content" role="main">
    <div class="hubSections">	
    <div class="hubSection1"></div>	
    <div class="hubSection2"></div>	
    <div class="hubSection3"></div>	
    <div class="hubSection4"></div>	
    <div class="hubSection5"></div>	
    </div>	
    </section>

    И стилизуем их в соответствии с занимаемыми ими ячейками сетки, в 100% по ширине (width) и высоте (height). Я показал здесь hubSection1, другие выглядят точно так же, имея лишь другие номера столбцов (4, 6, 8 и, соответственно, 10).

    .homepage .hubSection1 {	
    -ms-grid-row: 1;	
    -ms-grid-column: 2; /* 4 для hubSection2, 6 для hubSection3, и так далее. */
    width: 100%;	
    height: 100%;	
     }

    Создание макетов разделов

    Сейчас мы можем взглянуть на содержимое каждого раздела. В зависимости от того, что вы хотите отобразить, и как отображенные разделы должны взаимодействовать, вы можете снова просто использовать макет (CSS-сетку, или, возможно, гибкое окно), или использовать элементы управления наподобие ListView. Разделы hubSection3 и hubSection5 имеют пустые пространства в низу, поэтому они могут быть элементами управления ListView с изменяющимся количеством элементов. Обтатите внимание на то, что если мы создаём список с более чем 9 или 6 элементами, соответственно, мы захотим, настроить размеры столбцов во всей сетке, захотим сделать ширину элемента section больше, но давайте предположим, что дизайн требуется для максимум 6 и 9 элементов в разделах.

    Скажем так же, что мы хотим, чтобы каждый из разделов был интерактивен, когда прикосновение к элементу запускает навигацию к странице детальной информации. (В этом примере не показаны заголовки групп, используемые для навигации к странице группы). Мы просто используем ListView в каждом из разделов, где каждый из ListView будет иметь собственный источник данных. Для hubSection1 нам понадобится использовать объединение ячеек, в остальных же группах вполне подойдут декларативные шаблоны. Ключевое соглашение, касающееся всех этих групп, заключается в том, чтобы стилизовать элементы таким образом, чтобы они хорошо вписались в базовые размеры, которые мы используем. И, возвращаясь к общему стилю приложения, расстояние между изображениями элементов должно быть 10 пикселей, расстояние между столбцами со смешанным содержимым (hubSection4 и hubSection5) должно быть 40 пикселей (что может быть установленно с помощью подходящих CSS-полей).

    Подсказка. Если вы хотите сделать определенные области вашего содержимого невыделяемыми, используйте атрибут -ms-user-select в CSS для элемента div. Обратитесь к примеру: "Невыделяемые области содержимого с CSS-атрибутом -ms-user-select" (http://code.msdn.microsoft.com/windowsapps/Unselectable-content-areas-963eccd9).

    Точки прикрепления

    Если вы запустите упражнение HubPage и поработаете немного с ним, используя жесты инерционной прокрутки (то есть, такие, когда сдвиг элемента продолжается даже после того, как вы убрали палец; подробнее об этом - в лекции 3 курса "Пользовательский интерфейс приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript"), вы заметите, что сдвиг может остановиться в любом месте. Вам и вашему дизайнеру это может понравится, но во многих сценариях имеет смысл автоматическая остановка сдвига на границе раздела или группы. Для сенсорного взаимодействия это можно реализовать с использованием CSS-стилей для точек прикрепления (snap points), как описано в нижеприведенной таблице. Это - стили, которые вы добавляете к элементу, поддерживающему сдвиг, вместе со стилями, отвечающими за переполнение, иначе они не окажут нужного воздействия. Документацию по этому вопросу (и по некоторым другим) можно найти в материале "Сенсорное взаимодействие: изменение масштаба и сдвиг" (http://msdn.microsoft.com/ru-ru/library/windows/apps/hh453816.aspx).

    СтильОписаниеСинтаксис значений
    -ms-scroll-snap-points-xЗадаёт точку прикрепления для оси Х snapInterval(start<length>, step<length>) | snapList(list<lengths>)
    -ms-scroll-snap-points-yЗадаёт точку прикрепления по оси YsnapInterval(start<length>, step<length>) | snapList(list<lengths>)
    -ms-scroll-snap-typeЗадаёт, точка прикрепления какого типа должна быть использована для элемента: none отключает точку прикрепления, mandatory всегда осуществлять сдвиг до остановки на точке прикрепления (что включает в себя окончание инерционного сдвига), и proximity воздействовать на процесс сдвига лишь в том случае, если движение, на самом деле, заканчивается "очень близко" к точке прикрепления. Использование mandatory, таким образом, приводит к сдвигу с шагом в один раздел/элемент, в то время, как proximity позволит "проскочить" очередную точку прикрепления при инерционном сдвиге. Так же обратите внимание на то, что перетаскивание пальцем (то есть, использование жеста, где нет инерционного движения) позволяет пользователю передвинуть элемент в позиции, отличающиеся от точек прикрепления.none | proximity | mandatory
    -ms-scroll-snap-xСокращение для комбинации -ms-scroll-snap-type и -ms-scroll-snap-points-x<-ms-scroll-snap-type> <-ms-scroll-snap-points-x>
    -ms-scroll-snap-yСокращение для комбинации -ms-scroll-snap-type и -ms-scroll-snap-points-y<-ms-scroll-snap-type> <-ms-scroll-snap-points-y>

    В таблице, <length> - это число с плавающей запятой, за которым следует указатель абсолютной единицы (cm, mm, in, pt или pc), или относительной единицы измерения (em, ex или px).

    Для того, чтобы добавить точку прикрепления к каждому из разделов нашей стартовой страницы, нам лишь нужно добавить два стиля точек прикрепления после overflow-x:

    .homepage section[role=main] {	
    overflow-x: auto;	
    -ms-scroll-snap-type: mandatory;	
    -ms-scroll-snap-points-x: snapList(0px, 670px, 1045px, 1715px, 1795px);
    }

    Обратите внимание на то, что показанные здесь точки прикрепления включают 120-пиксельную левую границу, таким образом, каждая выравнивается с разделом, расположенным под текстом заголовка. Таким образом, точка прикрепления 0px соответствует первому разделу, 670px - второму (80-пиксельный разделитель и 590-пиксельная ширина первого раздела) и так далее. Последняя точка прикрепления в 1895px, однако, не следует этому правилу, так как div не может быть сдвинут за эту точку. Это означает, что мы прикрепляем точку где-то в предпоследней секции, но отображаем последнюю секцию и её 80-пиксельную границу.

    После этих изменений, мы обнаружите, что при прокрутке осуществляются остановки (приятно анимированные) точно на границах разделов. Отметьте, что для стартовой страницы, наподобие этой, использование точек прикрепления типа proximity обычно подходит больше. Обязательные точки прикрепления (mandatory) предназначены больше для элементов, с которыми невозможно взаимодействовать или работать без того, чтобы видеть их целиком, как, например, при пролистывании наборов фотографий, статей и так далее. (Элемент управления FlipView это использует).

    Для того, чтобы узнать об этом больше, в том числе - о некоторых других стилях -ms-scroll-* и -ms-content-zoom-*, об ограничителях прокрутки, обратитесь к примеру: "HTML-прокрутка, сдвиг, изменение масштаба" (http://code.msdn.microsoft.com/windowsapps/Scrolling-panning-and-47d70d4c). Обратите, так же внимание на то, что точки прикрепления предназначены не только для использования с элементом управления ListView, они предназначены и для использования в ваших собственных макетах.

    Разные состояния просмотра приложения

    Если в чем-то, касающимся макета приложения для Магазина Windows, и можно быть уверенным, так в том, что режим его отображения, весьма вероятно, будет часто меняться. Во-первых, авто-поворот экрана, особенно, на планшетных, переносных устройствах - делает очень простым и быстрым переключение между альбомной и портретной ориентациями экрана (пользователю не придётся столкнуться с настройкой драйвера дисплея). Во-вторых, устройство может быть подключено к внешнему дисплею, а это означает, что приложение нуждается в самостоятельной настройке на различные разрешения, и, возможно, на различные плотности пикселей. В-третьих, у пользователя есть возможность, в альбомном режиме, "прикреплять" приложение у левой или правой части экрана, когда прикрепленное приложение отображается в области шириной в 320 пикселей, а другое приложение выводится в зоне "заполняющего" просмотра, занимая остаток дисплея. Это можно сделать, используя жесты, мышь, или используя сочетания клавиш Win+. (точка), Win+> (Shift+точка). (Для прикрепленного режима требуется, как минимум, дисплей с разрешением 1366х768, иначе он будет отключен).

    Вам, определенно, захочется протестировать своё приложение со всеми этими вариантами: состояния просмотра, размеры дисплеев, плотностью пикселей. Работу в разных состояниях просмотра можно тестировать напрямую, на любом компьютере, а вот для двух последних вариантов нужны специальные инструменты, которые предоставляют имитатор Visual Stuido и закладка Устройство (Device) в Blend ,позволяя вам имитировать различные условия. Нас сейчас интересует вопрос, как приложение будет действовать при различных условиях просмотра.

    Состояния просмотра

    В лекции 1 были представлены четыре состояния просмотра, вспомнить о них вы можете, посмотрев на Рис. 1.6. Добавим сейчас следующий уровень точности к их описанию, рассмотрев следующую таблицу. Она включает в себя изображения пространства, которое занимают приложения, описания состояний просмотра и идентификаторов этих состояний и в WinRT (в перечислении Windows.UI.ViewManagement.ApplicationViewState (http://msdn.microsoft.com/library/windows/apps/windows.ui.viewmanagement.applicationviewstate.aspx), и в характеристике -ms-view-state (http://msdn.microsoft.com/library/windows/apps/hh465826.aspx) CSS-медиазапросов.

    Пространство, занимаемое приложением (Голубое)Подробности
    Приложение занимает весь экран в альбомном режиме. WinRT: fullScreenLandscape -ms-view-state: fullscreen-landscape
    Приложение занимает либо левую, либо правую часть экрана в альбомном режиме, на области, ограниченной шириной в 320 пикселей. Это означает, что вам не нужно создавать дизайн для всех возможных размеров среди прикрепленных, заполненных (смотрите ниже) и полноэкранных состояний просмотра. WinRT: snapped -ms-view-state: snapped
    Приложение занимает область экрана, находящуюся рядом с прикрепленным приложением. Ширина области, доступной приложению, равняется ширине экрана за вычетом 320 пикселей и 22 пикселей для элемента-разделителя. WinRT: filled -ms-view-state: filled
    Приложение в портретном режиме WinRT: fullScreenPortrait -ms-view-state: fullscreen-portrait

    Снова хочу напомнить, что каждую страницу вашего приложения нужно подготовить для всех четырех режимов просмотра (с некоторыми исключениями, которые описаны во врезке "Предпочтительная ориентация и блокировка ориентации"). Режимы просмотра всегда находятся под контролем пользователя, поэтому любая страница может оказаться в любом режиме просмотра в любое время, даже при старте. Повторяйте этот как мантру, так как многие разработчики и дизайнеры об этом забывают!

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

    Дизайн приложения, таким образом, включает все режимы просмотра для каждой страницы, так же, как мы поступили с описаниями страниц "Here My Am!" в лекции 2. В то же время, обработка режимов просмотра для каждой страницы не подразумевает четыре разных реализации приложения. Режимы просмотра это не более чем разные визуальные представления одного и того же содержимого страниц, как описано в "Руководстве по прикрепленному и заполненному представлениям" (http://msdn.microsoft.com/library/windows/apps/hh465371.aspx). Таким образом, переключение между режимами просмотра всегда сохраняет состояние приложения и его страниц - оно никогда не изменяет режим работы приложения или не осуществляет навигацию на другую страницу. Единственное исключение из этого правила сущестует, если приложение по веским причинам не может работать в прикрепленном режиме (как, например, игра, которой нужно определенное экранное пространство). В таком случае приложение может вывести сообщение об этом, вместе с инструкцией вроде "Прикоснитесь здесь, чтобы продолжить", что позволяет пользователю выразить таким образом своё намерение. В ответ на команду пользователя, приложение может вызвать tryUnsnap - это единственный программный API, который может воздействовать на состояния просмотра. Состояния просмотра, другими словами, всегда меняются по инициативе пользователя, и нет API для установки состояний просмотра, и нет способа для того, чтобы задавать их при запуске приложения.. Не используйте, однако, эту возможность для того, чтобы "срезать углы". Попытайтесь сохранить как можно больше возможностей приложения в прикрепленном режиме.

    Подсказка. Воспринимайте прикрепленный режим просмотра как дополнительный, ценный режим, где основная информация страницы по-настоящему заметна. Другими словами, рассматривайте прикрепленный режим как возможность, а не как тяжёлое бремя.

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

    Врезка: Предпочтительная ориентация и блокировка ориентации

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

    Для ясности, приложение всё еще должно работать в трех режимах: полноэкранном альбомном, в режимах заполняющего и прикрепленного просмотра. Предпочтительная ориентация обычно касается выбора между альбомной и портретной, и это влияет на ориентацию экрана-заставки и других страниц приложения. Это, кроме того, позволяет автоматически менять режим отображения, когда вы перелючаетесь между вашими приложениями и другими, у которых нет похожих предустановок.

    Для того чтобы сообщить Windows об этих предустановках, установите подходящие флаги в группе параметров Поддерживаемые ориентации (Supported Orientations) на закладке Интерфейс приложения (Application UI) в редакторе манифеста:

    Множество подробностей о том, как всё это работает, можно найти в справке по InitialRotationPreference (http://msdn.microsoft.com/library/windows/apps/Hh700342.aspx). Я хочу, кроме того, расссказать о свойствах Windows.Graphics.Display.DisplayProperties.autoRotationPreferences (http://msdn.microsoft.com/library/windows/apps/windows.graphics.display.displayproperties.autorotationpreferences.aspx) и currentOrientation (http://msdn.microsoft.com/library/windows/apps/windows.graphics.display.displayproperties.currentorientation.aspx) дл программного управления ориентацией. Для демонстрации, обратитесь к примеру "Предустановки автоповорота устройства" (http://code.msdn.microsoft.com/windowsapps/Auto-Rotation-Preferences-87ae2902).

    Обработка состояний просмотра

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

    Лучше всего думать о состояниях просмотра в терминах видимости элементов, их размеров, взаимного расположения на странице. При таком подходе, основная часть работы может быть выполнена посредством CSS-медиа запросы с использованием возможности -ms-view-state. Мы видели это в приложении "Here My Am!" из лекции 2. Шаблон проекта Приложение таблицы так же это демонстрирует. Вот как этим медиа-запросы выглядят в CSS:

    @media screen and (-ms-view-state: fullscreen-landscape) {
    /* ... */
    }
    
    @media screen and (-ms-view-state: filled) {
    /* ... */
    }
    
    @media screen and (-ms-view-state: snapped) {
    /* ... */
    }
    
    @media screen and (-ms-view-state: fullscreen-portrait) {
    /* ... */
    }
    
    /* Синтаксис для комбинирования медиа-запросов (разделены запятыми) */	
    @media screen and (-ms-view-state: fullscreen-landscape),
    
    screen and (-ms-view-state: fullscreen-portrait), screen and (-ms-view-state: filled) {
    /* ... */	
    }

    Кроме того, весьма разумно добавить другие выражения к этим запросам, такие, как and (min-width: "1600px"), так как вы можете выполнять множество различных настроек, основываясь на разрешении экрана.

    Для приложений Магазина Windows применяйте возможности обработки режимов просмотра в медиа-запросах вместо состояний, хранящихся в свойстве CSS Таким образом, состояния просмотра не сообщаются страницам, загруженным в iframe, в веб-контексте. Подобные страницы могут использовать стандартные CSS-медиа запросы для того, чтобы сделать вывод о состоянии просмотра, или окружающая страница, исполняющаяся в локальном контексте, может передать сведения о состоянии просмотра в iframe с помощью postMessage..

    Например, следуя стандартному алгоритму CSS, и полноэкранный портретный (fullscreen portrait), и прикрепленный (snapped) режимы детектируются как orientation: portrait, так как соотношение сторон экрана в таких режимах указывает на его вертикальное расположение. Однако, прикрепленный режим подразумевает иное намерение пользователя, чем полноэкранный портретный. В прикрепленном режиме вы скорее хотите видеть наиболее важные части приложения, нежели копию портретного макета в пространстве шириной 320 пикселей.

    Обычный подход заключается в том, чтобы размещать правила, касающиеся полноэкранного альбомного режима просмотра, в верхней части CSS-файла и затем выполнять тонкие настройки внутри конкретных медиа-запросов. Мы сделали это с "Here My Am!" в лекции 2, где стиль по умолчанию работает для режимов fullscreen-landscape и filled, и нам нужно было задать специфические правила лишь для режимов snapped и fullscreen-portrait.

    Совет. При стилизации приложения в Blend, в панели Правила стилей (Style Rules)существуют интуитивно понятные визуальные подсказки, которые позволяют контролировать точную точку вставки любого нового CSS-стиля в заданной таблице стилей. С помощью этого средства, которое выглядит как оранжевая линия на рисунке ниже, и как показано в Video 2.2., вы можете указать точное место вставки стилей для конкретных медиа-запросов внутри медиа-запроса.

    В некоторых случаях обработка медиа-запросов в декларативном CSS недостататочна. Когда основное содержимое отображается на странице, содержащей ListView с макетом gridLayout, которая прокручивается в горизонтальном направлении, обычно макет переключают на ListLayout при переходе в прикрепленный режим. Вы можете, кроме того, как показано в материале: "Руководство по прикрепленному и заполненному представлениях" (http://msdn.microsoft.com/library/windows/apps/hh465371.aspx), преобразовать список кнопок в единый выпадающий элемент select для того, чтобы предложить пользователю те же функциональные возможности посредством более компактного пользовательского интерфейса. Для реализации подобного вам понадобится JavaScript.

    Для подобных целей вы можете задействовать стандартное Media Query Listener API в JavaScript. Данный интерфейс (часть W3C CSSOM View Module, http://dev.w3.org/csswg/cssom-view/) позволяет вам добавлять обработчики к изменениям состояний медиа-запросов. Для того, чтобы прослушивать событие перехода в режим прикрепленного просмотра, вы можете использовать код, подобный этому:

    var mql = window.matchMedia("(-ms-view-state: snapped)");
    mql.addListener(styleForSnapped);
    function styleForSnapped() {
    if (mql.matches) {	
    //...	
    }
    
    // Создайте прослушиватели для других состояний просмотра: full-screen, fill, и device-portrait
    // или обработайте все меди-запросы в едином обработчике, проверяя в нём текущее состояние просмотра.

    Вы можете видеть, что строка медиа-запроса, которую передают в window.matchMedia, это та же строка, котрая используется в CSS, и в обработчике вы, конечно, можете сделать всё, что нужно с помощью JavaScript.

    Совет. Убедитесь в том, что протестировали режимы просмотра приложения при возникновении события resuming, так как характеристики дисплея могут измениться, например, при подключении другого монитора или увеличение экранных элементов, выполненного с помощью команды панели чудо-кнопок Параметры > Изменение параметров компьютера > Специальные возможности (Settings > Change PC Setings > Ease of Access), которая ведет к окну, содержащему тумблер Увеличить все элементы на экране (Make Everything on the Screen Bigger). Воззможно, что ваше приложение будет восстановлено из фонового режима (из приостановленного состояния) в прикрепленный режим просмотра, пока ваше приложение приостановлено, могут поменяться размеры экрана. Поэтому тестируйте макет на корректную обработку события resuming при открытии приложения в прикрепленном режиме просмотра и при изменении параметров экрана.

    Обрабатывая изменения режимов просмотра (или события window.onresize), вы можете получить точные размеры окна приложения посредством свойств window.innerWidth и window.innerHeight. Свойства document.body.clientWidth и document.body.clientHeight позволяют узнать ту же информацию, что и из свойств clientWidth и clientHeight любого элемента (наподобие div), который занимает 100% тела документа. Внутри события resize так же доступны свойства args.view.outerWidth и args.view.outerHeight.

    В CSS так же доступны сведения о высоте и ширине окна просмотра (vh и vw, соответственно). Вы можете поставить перед ними префикс в виде процентов, например, 100vh - это 100% высоты окна просмотра, и 3.5vw - это 3.5% ширины окна просмотра. Эти переменные так же могут быть использованы в выражениях CSS calc.

    Текущий режим просмотра доступен посредством свойства Windows.UI.ViewManagement.ApplicationView.value. Его значения берутся из перечисления Windows.UI.ViewManagement.ApplicationViewState, как показано в вышеприведенной таблице. В предыдущих лекциях мы видели применение этих механизмов. Например, элементы управления страниц (речь о них шла в лекции 3) обычно проверяют состояние просмотра в их методе ready и напрямую получают эти состояния в своём методе updateLayout. На самом деле, каждый метод элемента управления страницы groupedItem в проекте Приложение таблицы чувствителен к изменению состояния просмотра. Взгляните на код, взятый из pages/groupedItems/groupedItems.js:

    // Несколько строк и комментариев опущено	
    var appView = Windows.UI.ViewManagement.ApplicationView;	
    var appViewState = Windows.UI.ViewManagement.ApplicationViewState;
    var nav = WinJS.Navigation;	
    var ui = WinJS.UI;	
    
    ui.Pages.define("/pages/groupedItems/groupedItems.html", {
    initializeLayout: function (listView, viewState) {
    if (viewState === appViewState.snapped) { listView.itemDataSource = Data.groups.dataSource; listView.groupDataSource = null;
    listView.layout = new ui.ListLayout();
    } else {
    listView.itemDataSource = Data.items.dataSource;
    listView.groupDataSource = Data.groups.dataSource;
    listView.layout = new ui.GridLayout({ groupHeaderPosition: "top" });
    }
    },
    
    itemInvoked: function (args) {
    if (appView.value === appViewState.snapped) {
    // Если страница в прикрепленном режиме, пользователь вызывает группу. 
    var group = Data.groups.getAt(args.detail.itemIndex); nav.navigate("/pages/groupDetail/groupDetail.html", { groupKey: group.key });
    } else {
    // Если страница не в прикрепленном режиме, пользователь активирует элемент. 
    var item = Data.items.getAt(args.detail.itemIndex); nav.navigate("/pages/itemDetail/itemDetail.html",
    { item: Data.getItemReference(item) });
    }
    },
    
    ready: function (element, options) {
    // ...	
    this.initializeLayout(listView, appView.value);
    // ...	
    },	
    // Эта функция обновляет макет страницы в ответ на изменения viewState. 
    updateLayout: function (element, viewState, lastViewState) {
    var listView = element.querySelector(".groupeditemslist").winControl;
    if (lastViewState !== viewState) {
    if (lastViewState === appViewState.snapped ||
    viewState === appViewState.snapped) {
    var handler = function (e) {
    listView.removeEventListener("contentanimating", handler, false);
    e.preventDefault();
    }
    listView.addEventListener("contentanimating", handler, false);
    this.initializeLayout(listView, viewState);
    }
    }
    }
    }
    });

    В первую очередь, метод initializeLayout, который вызывается и из ready и из updateLayout проверяет текущее состояние просмотра и соответствующим образом настраивает элемент управления ListView. Если вы помните из лекции 5, во время исполнения программы можно и настраивать ListView и менять его источник данных. Здесь мы используем ListLayout со списком групп в прикрепленном состоянии просмотра и gridLayout со сгруппированными элементами в других режимах. Это показывает, как мы показываем то же самое содержимое, но в более сжатом формате, скрывая отдельные элементы в прикрепленном режиме. Из-за этого itemInvoked так же проверяет режим отображения, так как элементы списка - это группы в прикрепленном режиме и в таком случае навигация осуществляется на страницу сведений о группе вместо перехода на страницу детальной информации об элементе.

    Что касается updateLayout, он активируется из обработчика события window.onresize в коде PageControlNavigator (смотрите js/navigator.js в шаблоне проекта Приложение таблицы). Этот обработчик передаёт сведения о новом и предыдущем состоянии просмотра в updateLayout. Если эта функция обнаруживает, что мы переключились в прикрепленный режим или переключились из него, она сбрасывает к исходному состоянию ListView посредством initializeLayout. И, так как мы меняем источник данных ListView, здесь нет нужды в воспроизведении анимации входа или перехода. Небольшая уловка, работающая с событием contentanimating просто подавляет анимацию.

    Врезка: Физическая ориентация экрана

    Полноэкранный альбомный и полноэкранный портретный режимы просмотра предоставляют некоторую информацию о том, как устройство, на самом деле, ориентировано в пространстве, но подобная информация может быть гораздо точнее получена из свойств объекта Windows.Graphics.Display.DisplayProperties (http://msdn.microsoft.com/library/windows/apps/windows.graphics.display.displayproperties.aspx). В частности, свойство currentOrientation содержит значение из перечисления Windows.Graphics.Display.DisplayOrientations (http://msdn.microsoft.com/library/windows/apps/windows.graphics.display.displayorientations.aspx), что показывает, как устройство повёрнуто по отношению к nativeOrientation (и вызывает, при необходимости, событие orientationchanged). Эти данные позволят вам узнать, например, находится ли устройство экраном вниз, по отношению к небу, что может быть полезным для любого приложения, реализующего дополненную реальность, такую, как звёздная карта.

    Похожим образом, API Windows.Devices.Sensors (лекции 3 курса "Пользовательский интерфейс приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript".

    Размер экрана, плотность пикселей и масштабирование

    Не знаю о вас, но я, когда впервые узнал, что зона прикрепленного просмотра всегда имеет 320 пикселей в ширину - реальных пикселей, а не некое значение, выраженное в процентном выражении от ширины экрана - это меня озадачило. Не даст ли это совершенно разные впечатления от программы на разных дисплеях? Ответ на этот вопрос отрицательный. 320 пикселей - это около 25% от базового размера монитора 1366х768, что означает, что оставшиеся 75% - это вполне знакомые нам 1024х768. На 10-дюймовом дисплее это примерно 2.5 дюйма физического пространства дисплея. Пока всё понятно.

    На более крупных мониторах, с другой стороны, таких, как 2560x1440, эти 320 пикселей займут лишь 12,5% ширины, таким образом, макет полного экрана выглядит совершенно иначе. Однако, учитывая то, что подобные мониторы имеют 24-дюймовую диагональ, эти 320 пикселей снова занимают примерно 2.5 дюйма физического пространства экрана, что означает, что зона прикрепленного просмотра выглядит так же, как и ранее. Она лишь имеет больше вертикального пространства и оставляет после себя больше свободного места на экране.

    Это приводит нас к вопросу о плотности пикселей (pixel density). Что произойдёт, если ваше приложение окажется на по-настоящему маленьком дисплее, имеющем высокое разрешение? Очевидно, что на подобном дисплее зона в 320 пикселей будет немногим более дюйма. Есть у кого-нибудь увеличительное стекло?

    К счастью, это не тот вопрос, о котором беспокоятся приложения для Магазина Windows… Почти. Основное преимущество, которое получает пользователь от подобного дисплея - это более высокая чёткость изображения, но не большая плотность информации. Сенсорные цели должны быть одинаковых размеров на мониторах любых размеров, не важно, сколько пикселей они занимают. Ведь человеческие пальцы не меняются с развитием технологий! Для того, чтобы это учитывать, Windows автоматически уменьшает масштаб эффективного разрешения, которое сообщается приложению, что означает, что любые координаты, которые вы используете внутри приложения (в HTML, CSS и JavaScript) автоматически масштабируются к разрешению того устройства, на котором осуществляется вывод пользовательского интерфейса приложения. Это производится на низком уровне подсистем рендеринга HTML/CSS в хост-процессе приложения, всё выводится в соответствии с особенностями пикселей конкретного устройства для максимальной чёткости изображения.

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

    Разные размеры экрана, разная плотность пикселей может быть протестирована с помощью имитатора в Visual Studio, или на закладке Устройства (Device) в Blend. Последний вариант показан на Рис. 6.5. Здесь отображены применимый DPI и фактор масштабирования. 100% масштаб означает, что приложению напрямую сообщают о разрешении устройства. 140% и 180%, с другой стороны, что означает, что имеет место масштабирование. При размерах экрана 10.6 дюйма, разрешении 2560х1440 и масштабировании в 180%, например, приложение увидит данный экран как экран с размерами 1422х800 (2560/1.8 на 1440/1.8), что очень близко к стандартному дисплею 1366х768. Похожим образом, при размерах экрана 10.6 дюйма и разрешении 1920х1080 масштабирование в 140% покажет приложению экран размером 1371х771 (1920/1.4 на 1080/1.4). И в том и в другом случаях макет, разработанный в расчёте на экран 1366х768 полностью подходит, хотя вы, конечно, можете настроить его так точно, как захотите.

    Совет. Если ваше приложение имеет фиксированный макет (fixed layout) (смотрите раздел "Фиксированные макеты и элемент управления ViewBox" ниже), вы можете разрешить вопрос разной плотности пикселей просто используя графические ресурсы, масштабированные до 200% по отношению к вашему стандартному дизайну. Это так, потому что фиксированный макет может быть масштабирован к произвольным размерам, в итоге, изображения, имеющие изначально масштаб 200% хорошо масштабируются в любом случае. Подобное приложение не нуждается в предоставлении вариантов изображений, которые использует, в масштабах 100%, 140% и 180%. (рис 6.5) Параметры для задания размеров дисплея и плотностей пикселей на закладке Устройство (Device) в Blend

    Как отмечено ранее, работая с состояниями просмотра, вы можете программным способом определять точный размер окна вашего приложения посредством свойств window.innderWidth и window.innerHeight, свойствами document.body.clientWidth и document.body.clientHeight, и свойствами clientWidth и clientHeight любого элемента, который занимает 100% тела страницы. Внутри window.onresize вы можете использовать их (или свойства args.view.outerWidth и args.view.outerHeight) для того, чтобы подстроить макет приложения под изменения, касающиеся общего режима отображения приложения. Конечно, если вы используете что-то наподобие CSS-сетки с дробными размерами строк и столбцов, большинство подобных настроек макета будет выполнено автоматически.

    В любом случае, размер уже отражает автоматическое масштабирование с учетом плотности пикселей, таким образом, это - размеры, под которые вы адаптируете макет. Если вы хотите знать, каковы физические размеры дисплея, с другой стороны, вы можете воспользоваться свойствами window.screen.width и window.screen.height. Другие параметры дисплея можно обнаружить в объекте Windows.Graphics.Display.DisplayProperties (http://msdn.microsoft.com/library/windows/apps/br226143.aspx), в частности, такие, как logicalDPI и текущее значение resolutionScale. Последнее является значением перечисления Windows.Graphics.Display.ResolutionScale (http://msdn.microsoft.com/library/windows/apps/windows.graphics.display.resolutionscale.aspx), среди них - scale100Percent, scale140Percent, и scale180Percent. Возвращаемые значения этих идентификаторов - 100, 140 и 180, таким образом, вы можете использовать resolutionScale напрямую в вычислениях.

    Врезка: Хорошая возможность для удалённой отладки

    Работа с различными возможностями устройств предоставляет хорошую возможность поработать с удалённой отладкой, как описано в материале "Выполнение приложений для Магазина Windows на удаленном компьютере" (http://msdn.microsoft.com/library/windows/apps/hh441469.aspx). Такой подход позволит вам протестировать программу на различных дисплеях без необходимости устанавливать на каждом из устройств Visual Studio, и, кроме того, даст вам преимущества отладки с использованием нескольких мониторов. Вам лишь нужно установить и запустить средства удалённой отладки на целевом устройстве и убедиться, что оно подсоединено с помощью кабеля к той же сети, к которой подключен компьютер, на котором вы выполняете разработку. (Вам может понадобиться приобрести маленький USB-Ethernet-адаптер, если ваше устройство не имеет подходящего порта - удалённая отладка не работает через Интернет и при соединении устройств по беспроводной сети). Монитор удалённой отладки, выполняющийся на удалённой машине, сообщает о себе Visual Studio, исполняющемся на машине разработчика. Обратите внимание на то, что когда вы попытаетесь приступить к удалённой отладке в первый раз, вам предложат получить лицензию разработчика для целевого устройства, таким образом, это устройство должно быть подключено к Интернету в это время.

    Графические элементы, которые хорошо масштабируются

    Различные размеры экранов и плотности пикселей задают приложениям еще одну задачу, не связанную с макетом, касающуюся графических элементов, которые всегда должны выглядеть наилучшим образом. Конечно, вы можете рисовать графические элементы напрямую, используя элемен HTML5 canvas, на что мне хотелось бы обратить ваше внимание, так это на заранее сформированные графические ресурсы.

    Масштабируемая векторная графика HTML5 (scalable vector graphics, SVG) в данном случае очень кстати. Вы включаете встроенный SVG-код в свой HTML (включая фрагменты страниц), или вы можете хранить их в отдельных файлах и ссылаться на них как на атрибуты img.src. Один из самых простых способов использовать SVG - разместить элемент img внутри пропорционально настраиваемой ячейки CSS-сетки и задать стили width и height этого элемента в 100%. SVG автоматически масштабируется для заполнения ячейки, и так как ячейка изменяет размер вместе с элементом, являющимся контейнером для SVG, всё обрабатывается автоматически.

    У такого подхода есть одна проблема - SVG масштабируется с учетом соотношения сторон ячейки CSS-сетки, в которой находится, а оно не всегда может быть таким, как вам нужно. Для того, чтобы управлять этим поведением, убедитесь, что SVG имеет атрибуты viewBox и preserveAspectRatio, где cоотношение сторон, хранящееся в viewBox соответствует тому, которое задано свойствами SVG width и height:

    <svg xmlns:svg="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg" 
    xmlns:xlink="http://www.w3.org/1999/xlink" version="1.0"
    width="300"
    height="150" viewBox="0 0 300 150" preserveAspectRatio="xMidYMid meet">

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

    Что касается ресурсов в пакете приложения, мы уже видели, как работать с различными плотностями пикселей в лекции 3, посредством суффиксов к именам файлов .scale-100, .scale-140, и .scale-180. Этот подход работает для любых изображений в вашем приложении, используемых во всех случаях, будь это изображение для экрана-заставки, изображения плиток и другие графические ресурсы, на которые есть ссылки в манифесте. Таким образом, если у вас есть растровое изображение, имеющее имя banner.png, вы создатите три изображения в пакете приложения, которые будут называться banner.scale-100.png, banner.scale-140.png, и banner.scale-180.png. Затем вы можете просто ссылаться на базовое имя элемента в CSS или в конструкциях вида <img src= "images/banner.png"> и background-image: url('images/banner.png'), и загрузчик ресурсов Windows чудесным образом автоматически загрузит изображение, имеющее подходящий масштаб. (Если файлы с суффиксами .scale-* не найдены, загрузчик будет искать файл banner.png). Мы увидим даже больше подобных чудес в лекции 6 курса "Программная логика приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript и их взаимодействие с системой", где мы так же добавим варианты для различных языков и контрастных цветовых схем, которые представляют дополнительные собственные суффиксы.

    Если вам не по душе подобная схема именования файлов, знайте, что вместо этого вы можете использовать похожим образом именованные папки. Таким образом, для реализации этого подхода вам понадобятся папки с именами scale-100, scale-140, и scale-180, расположенные в папке изображений и содержащие файлы с неизмененными именами (наподобие banner.png).

    В CSS вы так же можете использовать медиа-запросы с установками max-resolution и min-resolution для управления тем, какие изображения будут загружены. Помните, однако, что CSS опирается на логическое DPI, а не на физическое DPI, граница для каждого фактора масштабирования указана далее (значения DPI здесь слегка отличаются от тех, которые даны в документации, так как они получены из эмпирических тетстов; документация предлагает, соответственно, значения в 134, 135 и 174 dpi).

    @media all and (max-resolution: 134dpi) {
    /* масштаб 100% */
    }
     
    @media all and (min-resolution: 135dpi) {
    /* масштаб 140% */
    }
    
    @media all and (min-resolution: 174dpi) {
    /* масштаб 180% */
    }

    Как разъяснено в "Руководстве по масштабированию в зависимости от плотности пикселей" (лекцию 2 курса "Программная логика приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript и их взаимодействие с системой", "Плитки, уведомления, экран блокировки и фоновые задачи", раздел "Использование локальных изображений и изображений, полученных из Web" для того, чтобы найти сведения о том, как при обновлении плиток данные механизмы используются для масштабирования, учёта контрастных схем и языковых особенностей.

    Вы можете программным образом получить свойства logicalDpi и resolutionScale из объекта Windows.Graphics.Display.DisplayProperties. Событие logicaldpichanged (событие WinRT) может быть, так же, использовано для проверки изменений resolutionScale, так как эти два параметра всегда связаны. Использование данных API проиллюстрировано примером "Масштабирование в соответствии с DPI" (http://code.msdn.microsoft.com/windowsapps/Scaling-sample-cf072f4f).

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

    Адаптивные и фиксированные макеты для дисплеев различных размеров

    Так же, как каждая страница вашего приложения нуждается в подготовке для различных состояний просмотра, страницы нуждаются и в подготовке для экранов различных размеров. Я рекомендую почитать "Руководство по масштабированию для различных экранов" (http://msdn.microsoft.com/library/windows/apps/hh780612.aspx), где есть ценная информация о том, с дисплеями каких размеров может столкнуться ваше приложение. Из этого руководства мы можем сделать вывод о том, что размер самой маленькой области прикрепленного просмотра равняется 320х768, минимальный размер области заполняющего просмотра - 1024х768, и минимальный размер области полноэкранного просмотра (портретного и альбомного) - 1280х800 и 1366х768. Это - базовые параметры для вашего дизайна.

    Таким образом, дисплеи лишь увеличиваются, по сравнению с базовыми параметрами, в итоге мы приходим к вопросу: "Что делать с дополнительным пространством?". Первая часть ответа заключается в том, чтобы заполнить экран. Ничего не выглядит глупее, чем приложение, запущенное на 27-дюймовом мониторе и использующее при этом лишь область размером 1366х768, для которой оно было разработано. В подобной ситуации приложение займёт лишь от четверти экрана, до, в лучшем случае, половины. Как я уже говорил много раз, представьте себе, какие обзоры и оценки может получить ваше приложение в Магазине Windows, если вы не будете обращать внимание на подобные детали!

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

    Врезка: Параметр "Увеличить все элементы на экране"

    Среди параметров компьютера (чудо-кнопка Параметры > Изменение параметров компьютера > Специальные возможности (Settings > Change PC Setings > Ease of Access)) есть тумблер Увеличить все элементы на экране (Make Everything on the Screen Bigger). Включение этого параметра позволяет эффективно увеличить размер экранных элементов примерно на 40%, что подразумевает то, что система сообщает приложениям о том, что размер экрана примерно на 30% меньше, чем текущее разрешение (похоже на уровень масштабирования в 140%). К сачтью, этот параметр отключён, если в итоге система вынуждена будет сообщить об экране, который меньше, чем 1024х768, в итоге, подобное разрешение - это самое меньшее, на что может рассчитывать ваше приложение. В любом случае, при изменении данного параметра вызывается событие Windows.Graphics.Display.DisplayProperties.logicalDpiChanged.

    Фиксированные макеты и элемент управления ViewBox

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

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

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

    Так как это - более распространённый подход, WinJS предоставляет встроенный элемент управления макетом именно для этой цели: WinJS.UI.ViewBox (http://msdn.microsoft.com/library/windows/apps/br229771.aspx) (не следует путать с атрибутом SVG viewBox). Как и в случае с другими элементами управления WinJS, вы можете объявить его, используя data-win-control в HTML, как показано ниже, где элемент viewBox может содержать один и только один дочерний элемент:

    <div data-win-control="WinJS.UI.ViewBox">
    <div class="fixedlayout">	
    <p>Content goes here</p>	
    </div>	
    </div>

    На самом деле, это всё, на что можно посмотреть при работе с ViewBox. У него нет параметров или свойств, нет методов и событий - всё очень просто! Обратите так же внимание на то, что так как ViewBox - это лишь элемент управления, вы можете использовать для любого содержимого с постоянным соотношением сторон в адаптивном макете. Он предназначен не только для создания макета целой страницы.

    Для установки базисного размера ViewBox - размерностей, на которых будет основан ваш код - просто задайте параметры height и width его дочернего элемента в CSS. Например, для установки базисного размера в 1024х768, мы устанавливаем данные свойства в правиле для класса fixedLayout:

    fixedlayout { width: 1024px; height: 768px;
    }

    Как только создан экземпляр объекта ViewBox, он прослушивает события window.onresize и затем применяет 2D-трансформацию CSS к дочерним элементам, основываясь на разнице между базисным размером и реальным размером. Это позволяет сохранить соотношение сторон. Это работает и для увеличения и для уменьшения масштабов отображения содержимого. Автоматически применяется и размещение полос пустого пространства сверху и снизу или справа и слева от дочернего элемента, вы можете задать внешний вид этих областей (на самом деле, любых областей, которые не перекрывает дочерний элемент), используя класс win-viewbox. Как всегда, используйте данный селектор в области видимости конкретного элемента управления, если вы в приложении пользуетесь более чем одним элементом ViewBox, если только вы не хотите, чтобы подобный стиль был применен ко всем элементам.

    Базовая структура выше - это то, что вы получаете при создании нового приложения по шаблону Приложение с фиксированным макетом в Visual Studio и Blend. Как показано здесь, создаётся макет с базисным размером 1024х768, но вы можете использовать любой желаемый размер.

    CSS для этого шаблона проекта показывает, что вся страница стилизована как гибкое окно CSS для того, чтобы ViewBox был отцентрован, и то, что элементу fixedLayout задана сетка по умолчанию:

    html, body {	
    height: 100%;
    margin: 0;	
    padding: 0;	
     }
    body {	
    -ms-flex-align: center;	
    -ms-flex-direction: column;
    -ms-flex-pack: center;	
    display: -ms-flexbox;	
    }
    .fixedlayout {	
    -ms-grid-columns: 1fr;
    -ms-grid-rows: 1fr;	
    display: -ms-grid;	
    height: 768px;
    width: 1024px;
    }

    Если вы создаете проект по этому шаблону в Blend, добавьте стиль границы к правилу fixedLayout (наподобие border: 2px solid Red;), и поэкспериментируйте с режимами отображения и настройками дисплея на закладке Устройство (Device). Таким образом вы можете понаблюдать за тем, как ViewBox реализует возможности масштабирования без каких-либо усилий с вашей стороны. Для того, чтобы показать это ярче, упражнение fixedLayout для этой лекции содержит измененный на canvas дочерний элемент ViewBox, в котором нарисована сетка 4х3 (соответствующая соотношению сторон экрана 1024х768) из квадратных ячеек размером по 256 пикселей, содержащих окружности. Как показано на Рис. 6.6, квадраты и круги не превращаются в прямоугольники и овалы, когда мы переключаем состояния просмотра и размеры экранов, автоматически добавляются полосы пустого пространства (применяя стиль background-color к классу win-viewbox).

    Врезка: Растровая графика и фиксированные макеты

    Если вы используете с ViewBox растровую графику, настройте их в соответствии с максимальным разрешением 2560х1440, таким образом, они будут хорошо выглядеть на больших дисплеях и будут отображаться с уменьшением масштаба (вместо увеличения) на дисплеях меньшего размера. Вы можете воспользоваться и альтернативным подходом, загружая различные изображения (посредством различных URI для img.src), которые наилучшим образом подходят для наиболее широко распространённых размеров дисплея.

    Обратите внимание на то, что всё еще применимо масштабирование разрешения. Если приложение исполняется на дисплее высокой плотности размером 10.6 дюймов и разрешением 2560х1440 (масштабирование 180%), приложение, и, таким образом, ViewBox опознают такой дисплей как дисплей меньшего размера. Но если вы поддерживаете графические элементы для собственного разрешения устройства, они будут выглядеть чётко при выводе на экран.

    (рис 6.6) Масштабирование фиксированного макета с использованием элемента управления WinJS.UI.ViewBox, показано добавление полос по краям эркрана в полноэкранном режиме 1366х768 (слева) и в прикрепленном режиме просмотра (справа)

    Адаптивные макеты

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

    Подобные макеты легче всего реализовать с использованием CSS-сетки, где пропорциональные строки и столбцы автоматически увеличиваются или уменьшаются; элементы внутри ячеек сетки соответствующим образом подстраивают свои размеры. Это можно наблюдать в шаблонах проектов для Visual Studio и Blend, особенно - в шаблоне Приложение таблицы. На типичном дисплее с разрешением 1366х768 вы можете видеть некоторое количество элементов, как показано в верхней части Рис. 6.7. Переход на 27-дюймовый дисплей с разрешением 2560х1440 позволит вам увидеть гораздо больше данных, это можно видеть в нижней части рисунка.

    (рис 6.7) Адаптивный макет проекта, построенного по шаблону Приложение таблицы, для экрана с разрешением 1366х768 (сверху) и для экрана с разрешением 2560х1440 (снизу)

    Честно говоря, проект Приложение таблицы не выполняет особой обработки макета при изменении размеров экрана, отличающейся от того, что он выполняет для различных режимов просмотра. Из-за использования CSS-сеток и пропорциональных размеров ячеек, ячейка, содержащая элемент управления ListView, автоматически увеличивается. Элемент управления ListView самостоятельно просшушивает событие window.onresize, в итоге, нам не нужно отдельно управлять обновлением его макета.

    Общая стратегия работы с адаптивным макетом, таким образом, не вызывает затруднений:

  • Используйте везде, где возможно, CSS-сетку, для автоматической реализации адаптивного макета.
  • Просшуливание события window.onresize нужно для самостоятельного изменения расположения или размеров элементов, таких, как элемент HTML canvas.
  • Позвольте элементам управления прослушивать событие window.onresize для самостоятельной настойки их параметров. Это особенно важно для элементов управления для коллекций, наподобие ListView.
  • В качестве другого ориентира вы можете воспользоваться примером "Адаптивный макет с использованием CSS" (http://code.msdn.microsoft.com/windowsapps/Adaptive-layout-with-sample-062e7fe2), который применяет тот же подход, что и шаблон проекта Приложение таблицы, полагаясь на самостоятельную подстройку своих параметров элементами управления. В примере, вы увидите, что приложение не выполняет никаких прямых расчётов, основанных на размерах окна.

    Подсказка. Если у вас есть адаптивный макет и вы хотите использовать фоновое изображение, заданное в CSS, которое масштабируется вместе с собственным контейнером (вместо того, чтобы заполнять его, повторяясь), стилизуйте background-size либо задав значение contains, либо 100% 100%.

    Вам, как разработчику, должно быть понятно и то, что то, как приложение работает с экранами различных размеров - это вопрос дизайна. Вышеприведенная стратегия - это то, что вы используете для реализации дизайна, но дизайн определяет то, как всё будет выглядеть. Эти соображения, которых я здесь лишь кратко коснулся, описаны в материале "Руководство по масштабированию для различных экранов" (http://msdn.microsoft.com/library/windows/apps/hh780612.aspx):

  • Какие области являются фиксированными, а какие - адаптивными?
  • Как адаптивные области используют дополнительное пространство, включая подходы, с помощью которых эти области подстраиваются под дополнительное пространство?
  • Как взаимодействуют области с адаптивным макетом и области с фиксированным макетом в каркасе приложения?
  • Как полный макет приложения использует пространство, то есть, как к изменению размера адаптируются свободные пространства, не становится ли содержимое расположенным слишком плотно?
  • Как приложение использует многоколоночный текст?
  • Ответы на подобные вопросы помогут вам понять, как макету следует адаптироваться.

    Использование CSS-сетки

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

    Так как этот курс направлен на особенности разработки для Windows 8, я оставляю задачу разъяснения всех подробностей о сетке спецификациям W3C: http://dev.w3.org/csswg/css3-grid-layout/ и http://www.w3.org/TR/css3-grid-layout/. Эти материалы представляют собой общие руководства, которые помогут в понмании того, как настраиваются размеры строк и столбцов, особенно когда некоторые из них объявлены с фиксированными размерами, кого размер некоторых зависит от содержимого, а другие заданы так, чтобы они заполняли оставшееся пространство. Здесь много тонкостей!

    Так как эти спецификации, когда я пишу это, всё еще находятся в разработке, полезно точно знать, какие части спецификация реально поддерживаются подсистемой HTML/CSS, которой пользуются приложения для Магазина Windows.

    Для элемента, содержащего сетку, поддерживаемые стили весьма просты. Во-первых, используйте модели отображения -ms-grid и -ms-inline-grid (стиль display:). Позже мы вернемся к -ms-inline-grid.

    Во вторых, в элементах сетки используйте -ms-grid-columns и -ms-grid-rows для задания их расположения. Если оставить эти параметры незаданными, значение по умолчанию - это один столбец и одна строка. Поддерживается и синтаксис для задания повторяющихся конструкций, такой, как -ms-grid-columns: (1fr)[3];, что особенно удобно, когда у вас имеется повторяющиеся серии строк или столбцов, которые появляются внутри строк описаний. Как пример, следующие команды эквивалентны:

    -ms-grid-rows:10px 10px 10px 20px 10px 20px 10px;
    -ms-grid-rows:(10px)[3] (20px 10px)[2];	
    -ms-grid-rows:(10px)[3] (20px 10px) 20px 10px;	
    -ms-grid-rows:(10px)[2] (10px 20px)[2] 10px;

    То, как вы задаёте строки и столбцы - вопрос достаточно интересный, так как вы можете сделать некоторые из них фиксированными, некоторые - гибко меняющими размеры, а некоторые - ориентированными на размер содержимого. Этих целей можно достичь, используя следующие значения. Опять же, посмотрите документацию по особенностями использования спецификаторов max-content, min-content, minmax, auto, и fit-content, вместе со значениями, которые задаются в таких единицах измерения, как px, em, %, и fr. Приложения для Магазина Windows, так же, поддерживают, в качестве единиц измерения, такие показатели, как vh (высота окна просмотра) и vw (ширина окна просмотра).

    Внутри сетки, дочерние элементы располагаются в заданных строках и столбцах с заданными характеристиками выравнивания, объединения, расположения по слоям, используя следующие стили:

  • -ms-grid-column - определяет базовый столбец (нумерация начинается с 1) в сетке для дочернего элемента.
  • -ms-grid-row - определяет базовую строку (нумерация начинается с 1) в сетке для дочернего элемента.
  • -ms-grid-column-align и -ms-grid-row-align задаёт то, как дочерний элемент будет расположен в ячейке сетки. Допустимые значения - start, end, center и stretch (по умолчанию).
  • -ms-grid-column-span и -ms-grid-row-span показывает, будет ли дочерний элемент занимать одну строку и один столбец, или же несколько.
  • -ms-grid-layer управляет тем, как элементы сетки перекрываются. Это похоже на стиль z-index, используемый для элементов, которые можно позиционировать. Так как дочерние элементы сетки не позиционируются напрямую из CSS, позиционируясь, вместо этого, в соответствии с сеткой, -ms-grid-layer позволяет управлять этим.
  • Обратите особое внимание на то, что нумерация строк и столбцов начинается с 1, а не с 0. Перепрограммируйте ваш ум, ориентированный на JavaScript для того, чтобы это запомнить, так как вам понадобится небольшая трансляция адресов в том случае, если вы храните дочерние элементы в массиве, нумерация которого начинается с 0.

    Кроме того, обращаясь к любому из этих -ms-grid* стилей как к свойствам в JavaScript, опустите тире и переключитесь на написание адресов в "верблюжьем" (camel casing) стиле: msGrid, msGridColumns, msGridRowAlign, msGridLayer.

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

    Переполнение ячейки сетки

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

    Пример содержимого, которое выступает за пределы содержащей его ячейки можно найти в упражнении GridOverflow в дополнительных материалах к этой лекции. Здесь создана сетка из прямоугольных элементов, 4х4, но нижеприведенный код, размещенный в конце функции doLayout (js/default.js) размещает первый прямоугольник за пределами ячейки:

    children[0].style.width = "350px"; children[0].style.marginLeft = "150px"; children[0].style.background = "#fbb";

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

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

    Вертикальная центровка содержимого

    Где-то, в собственном опыте работы с CSS вы, возможно, сталкивались с неприятным поведением стиля vertical-align в попытке разместить фрагмент текста в центре или в нижней части элемента div. К несчастью, это не работает: этот стиль предназначен для ячеек таблицы и для встроенного содержимого (для того, чтобы задать, как текст и изображения, например, выравниваются относительно друг друга).

    В результате, для того, чтобы это реализовать, было разработано множество методов. Например, об этом идет речь здесь: http://blog.themeforest.net/tutorials/vertical-centering-with-css/. К несчастью, практически все эти методы основаны на фиксированной высоте - а это может работать для веб-сайта, но не подходит для адаптивных макетов, в которых нуждаются приложения для Магазина Windows. И единственный метод, который не использует фиксированную высоту, основан на применении встраиваемой таблицы. Эх.

    К счастью, и CSS-сетка, и гибкое окно (смотрите раздел "Макет элемента" ниже) позволяют легко решить эту проблему. В случае с сеткой, вы можете просто создать родительский элемент div с сеткой 1х1 и использовать стиль -ms-grid-row-align: center для дочернего элемента div (значение по умолчанию для которого - ячейка 1,1):

    <!-- В HTML -->	
    <div id="divMain">	
    <div id="divChild">	
    <p>Centered Text</p>
    </div>	
    </div>
    
    /* В CSS */
    #divMain { width: 100%; height: 100%; display: -ms-grid;
    -ms-grid-rows: 1fr;
    -ms-grid-columns: 1fr;
    }
    
    #divChild {
    -ms-grid-row-align: center;
    -ms-grid-column-align: center;
    
    /* Горизонтальное выравнивание текста так же работает с */
    /* text-align: center; */	
     }

    Решение этой проблемы даже проще с помощью макета на основе flexbox, где flex-align: center задаёт вертикальную центровку, flex-pack: center отвечает за горизонтальную центровку, и дочерний элемент div не нужен. Это тот же подход к стилизации, что применен в шаблоне Приложение с фиксированным макетом для центровки элемента ViewBox:

    <!-- В HTML -->	
    <div id="divMain">	
    <p>Centered Text</p>
    </div>	
    /* В CSS */
    #divMain { 
    width: 100%; height: 100%;
    display: -ms-flexbox;
    -ms-flex-align: center;
    -ms-flex-direction: column;
    -ms-flex-pack: center;
    }

    Код обоих методов можно найти в упражнении CenteredText к этой лекции. (Упражнение так же используется для демонстрации применения многоточий, в итоге он выглядит не точно так же, как показано выше).

    Масштабирование размеров шрифтов

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

    При работе с адаптивным макетом, обычно нужно, чтобы размер шрифта был пропорционален размерностям его родительского элемента. (Это не проблема, если родительский элемент имеет фиксированный размер, потому что так вы можете использовать шрифт фиксированного размера). К несчастью, процентные значения, используемые в стиле font-size в CSS, основаны на размере шрифта по умолчанию (1em), а не на размере родительского элемента, как в случае с height и width. Вам, вероятно, понравилось бы использование выражения наподобие font-size: calc(height * .4), но значения других CSS-стилей того же самого элемнта не доступны calc.

    Одно исключение из этого правила касается значения vh (которое можно использовать в calc). Если вы знаете, например, что текст, который вы хотите масштабировать, содержится в ячейке сетки, которая всегда занимает 10% от высоты окна вывода, и вы хотели бы, чтобы размер шрифта равнялся половине от этого значения, вы можете воспользоваться выражением font-size: 5vh (5% от высоты окна просмотра).

    Другой метод заключается в использовании SVG для вывода текста, где вы можете установить атрибут viewBox и задать font-size относительно этого viewBox. Затем, масштабирование SVG по отношению к ячейке сетки эффективно масштабирует и шрифт:

    <svg viewBox="0 0 600 400" preserveAspectRatio="xMaxYMax">
    <text x="0" y="150" font-size="200" font-family="Verdana"> Big SVG Text
    </text>
    </svg>

    Так же вы можете воспользоваться JavaScript для вычисления желаемого размера шрифта, основываясь на свойстве clientHeight родительского элемента. Если данный элемент находится в ячейке сетки, размер шрифта (и высотра строки) могут составить некоторый процент от высоты ячейки, таким образом, позволяя масштабировать шрифт вместе с ячейкой.

    Так же вы можете попытаться использовать элемент управления WinJS.UI.ViewBox. Если вам нужно, чтобы текст занял 50% элемента, содержащего его, поместите ViewBox в div, который настроен на размер, равняющийся 50% размера контейнера, и стилизуйте дочерний элемент элемента ViewBox с помощью position: absolute. Попытайтесь, для того, чтобы увидеть это, поместить нижеприведеннй код в default.html нового проекта, созданного на основе шаблона Пустое приложение:

    <div style="height:50%;">	
    <div data-win-control="WinJS.UI.ViewBox">	
    <p style="position:absolute;">Big text!</p>
    </div>	
    </div>

    Макет элемента

    До сих пор в этой лекции мы исследовали макеты уровня страницы, которые определяют то, как элементы верхнего уровня расположены на странице, обычно - с помощью CSS-сетки. Конечно, всё это - лишь HTML и CSS, поэтому вы можете использовать таблицы, разрывы строк и всё, что поддерживается подсистемой рендеринга, если это позволяет вам создавать макеты, подходящие для разных режимов просмотра и размеров дисплея.

    Важна и работа с шаблонами отдельных элементов, которые расположены в изменяющихся областях страницы. Таким образом, если вы задали сетку, определяющую общий вид страницы и получили с её помощью некоторое количество областей фиксированного размера (для заголовков, изображений в заголовке, панелей управления и так далее), оставшаяся область может сильно меняться в размере при изменении размеров окна. В этом разделе, таким образом, давайте взглянем на некоторые средства, которые мы можем применять в подобных областях: CSS-трансформации, гибкое окно, вложенные и встроенные сетки, многоколоночный текст, CSS-выражения и объединенные CSS-рамки. Информацию по этим и другим возможностям CSS, которые поддерживаются приложениями для Магазина Windows (такие, как фоны, границы, градиенты), можно найти в материале "Каскадные таблицы стилей" (http://msdn.microsoft.com/library/windows/apps/hh996828.aspx).

    2D и 3D-трансформации в CSS

    Практически невозможно размышлять о макетах для элементов не принимая во внимание CSS-трансформации. Трансформации - очень мощное средство, так как они делают возможным изменение отображения элемента, не воздействуя ни на последовательность элементов в документе, ни на общий макет. Это очень полезно для реализации анимаций и переходов. Трансформации широко используются библиотекой анимации WinJS, которые обеспечивают внешний вид и восприятие встроенных элементов управления, характерные для Windows 8. Как мы узнаем в лекции 5 курса "Пользовательский интерфейс приложений для Windows 8, созданных с использованием HTML, CSS и JavaScript", вы можете так же напрямую пользоваться этой библиотекой.

    CSS-трансформации можно использовать непосредственно, конечно, в любое время, когда вам нужно преобразовать, масштабировать, повернуть элемент. Приложения для Магазина Windows поддерживают и 2D (двумерные) и 3D (трехмерные) трансформации (http://dev.w3.org/csswg/css3-2d-transforms/Во время написания этого материала префиксы -ms-* для данных стилей уже не нужны, но всё еще поддерживаются.:

    CSS-стильСвойство JavaScript (element.style.)
    backface-visibilitybackfaceVisibility
    perspective, perspective-origin perspective, perspectiveOrigin
    transform, transform-origin, и transform-styletransform, transformOrigin, и transformStyle

    Подробности можно найти на странице "Трансформации" (http://msdn.microsoft.com/library/windows/apps/hh453377.aspx). Знайте так же, что так как хост-процесс приложения использует те же механизмы, что и Internet Explorer, трансформации используют все преимущества аппаратного ускорения.

    Гибкое окно (flexbox)

    Так же, как сетка - отличный инструмент для решения проблем макетов страниц, модуль гибкое окно CSS, описанный в http://www.w3.org/TR/css3-flexbox/, прекрасно подходит для работы с областями, размеры которых могут меняться, содержимое в которых нуждается в "заполнении" доступного пространства. Процититуем спецификацию W3C:

    В данной оконной модели, дочерние элементы окна размещаются либо горизонтально, либо вертикально, неиспользованное пространство может быть назначено конкретным дочерним элементом или распределено между такими элементами путём назначения 'flex' тем дочерним элементам, которые должны заполнять это пространство. Вложенность подобных окон (горизонтальное внутри вертикалного, или вертикальное внутри горизонтального) может быть использована для построения двумерных макетов.

    Так как спецификации гибкого окна представлены в форме чернового стандарта, конкретные стили, используемые в приложениях для Магазина Windows - это Если вы привыкли к стилям -ms-box* для гибких окон, Microsoft с тех пор следует спецификациям W3C, где ожидается последняя старшая редакция перед финальным принятием стандарта. Когда новый синтаксис заменит старый, старый не будет работать ни в приложениях для Магазина Windows, ни в Internet Explorer 10.. Полную справочную информацию по другим поддерживаемым свойствам вы можете найти на странице "Макет на основе гибкого окна ("Flexbox")" (http://msdn.microsoft.com/library/windows/apps/hh453474.aspx):

    CSS-стильСвойство JavaScript (element.style.)Значения
    -ms-flex-align msFlexAlign start | end | center | baseline | stretch
    -ms-flex-direction msFlexDirection row | column | row-reverse | column-reverse | inherit
    -ms-flex-flow msFlexFlow <direction> <pack> где <direction> это значение -ms-flex-direction и <pack> это значение -ms-flex-pack
    -ms-flex-orientmsFlexOrienthorizontal | vertical | inline-axis | block-axis | inherit
    -ms-flex-item-align msFlexItemAlign auto | start | end | center | baseline | stretch
    -ms-flex-line-pack msFlexLinePack start | end | center | justify | distribute | stretch
    -ms-flex-order msFlexOrder <integer> (порядковый номер группы)
    -ms-flex-pack msFlexPack start | end | center | justify
    -ms-flex-wrap msFlexWrap none | wrap | wrapreverse

    Как и для всех остальных стилей, Blend - это отличный инструмент, с помощью которого можно экспериментировать с различными стилями гибких окон, так как вы можете сразу же видеть эффект от их применения. Также полезно знать, что гибкое окно используется во многих местах WinJS и в шаблонах проектов, как мы видели ранее в случае с шаблоном Приложение с фиксированным макетом. В частности, возможности гибкого окна использует элемент управления ListView, это позволяет ему отображать больше элементов, когда доступно больше пространства. Элемент управления FlipView использует гибкое окно для центровки элементов. Элементы управления Ratings, DataPicker и TimePicker организуют свои внутренние элементы с использованием встроенного гибкого окна. Весьма вероятно, что ваши собственные пользовательские элементы управления будут поступать так же.

    Вложенные и встроенные сетки

    Так же, как и гибкое окно имеет модели блочного уровня и встроенные модели, существуют и встроенные сетки: display: -ms-inline-grid. В отличе от сетки блочного уровня, встроенный вариант позволяет вам располагать несколько сеток на одной и той же линии. Это показано в упражнении InlineGrid, где у нас есть три элемента div в HTML, которые можно переключать между встроенной моделью (по умолчанию) и моделью блочного уровня:

    //В обработчике activated	
    document.getElementById("chkInline").addEventListener("click", function () {
    setGridStyle(document.getElementById("chkInline").checked);	
    });	
    setGridStyle(true);
    
    //В любом месте в default.js 
    function setGridStyle(inline) {
    var gridClass = inline ? "inline" : "block";
    
    document.getElementById("grid1").className = gridClass;
    document.getElementById("grid2").className = gridClass;
    document.getElementById("grid3").className = gridClass;
    }	
    
    /* default.css */	
    .inline {	
    display: -ms-inline-grid;
    }	
    
    .block {
    display: -ms-grid;
    }

    При использовании встроенной сетки элементы выглядят так:

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

    Шрифты и переполнение текстом

    Как упоминалось ранее, типографика - это важный элемент дизайна приложений для Магазина Windows, и, в основном, стандартные стили шрифтов, использующие Segoe UI, уже заданы в таблицах стилей WinJS. В Windows SDK есть очень полезный пример "CSS-типографика" (http://code.msdn.microsoft.com/windowsapps/typography-JS-sample-e2df9eb4), где сравнивается элементы заголовков HTML и стили win-type-*, показывая запасные варианты шрифтов и использование двунаправленных шрифтов (с направлением слева направо и справа налево).

    Если говорить о шрифтах, пользовательские шрифтовые ресурсы, использующие правило @font-face в CSS, разрешены в приложениях для Магазина Windows. Для страниц локального контекста, свойство src правила должно ссылаться на шрифт файла, который находится в пакете (то есть, это URI, который начинается с / или с ms-appx:///). Страницы, исполняющиеся в веб-контексте, могут загружать шрифты из удалённых источников. Другой вопрос, касающийся текстов и типографики касается текста, который выходит за пределы выделенной для него области. Вы можете использовать стиль CSS text-overflow: ellipsis; для обрезки текста и добавления в конец текста …, и таблицы стилей WinJS содержат класс win-type-ellipsis для этих целей. В дополнение к установке text-overflow, этот класс так же добавляет overflow: hidden (для подавления появления полос прокрутки), и white-space: nowrap. Эти стили вы можете добавлять к любому текстовому элементу, когда вы хотите реализовать поведение, касающееся усечения текста.

    Спецификация W3C, касающася переполнения текстом, http://dev.w3.org/csswg/css3-ui/#text-overflow, содержит полезные сведения о том, что можно и что нельзя сделать в этой области. Одно из ограничений текущей спецификации заключается в том, что многострочный обтекающий текст не работает с усечением текста. Таким образом, вы можете использовать обтекание текстом с помощью стиля word-wrap: breakpword, но не можете совместить его с text-overflow: ellipsis (word-wrap имеет преимущество). Я так же узнал, что перетекающий текст из многострочной CSS-области (смотрите следующий раздел) работает в однострочной области с возможностью усечения текста, но text-overflow не применим к областям. В итоге, сейчас вы нуждаетесь в сокращении текста и ручной вставке многоточий, если текст занимает несколько строк.

    Для демонстрации сокращения текста и обтекания словами, посмотрите упражнение к этой лекции CenteredText.

    Многоколоночные элементы и области

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

    CSS3 предоставляет средства для создания многоколоночных макетов внутри элемента (смотрите http://www.w3.org/TR/css3-multicol/). С помощью этих средств вы можете настроить отдельный элемент так, чтобы он расположил своё содержимое в несколько колонок и указать множество параметров подобного макета. Соответствующие стили поддерживают и приложения для Магазина Windows (без необходимости использования префиксов поставщика):

    CSS-стилиСвойство JavaScript (element.style.)
    column-width и column-count (columns это сокращение) columnWidth, columnCount, и columns
    column-gap, column-fill, и column-span columnGap, columnFill, и columnSpan
    column-rule-color, column-rule-style, и columnRuleColor, columnRuleStyle, и columnRuleWidth
    column-rule-width (column-rule это сокращение для разделителей колонок)(columnRule это сокращение)
    break-before, break-inside, и break-after breakBefore, breakInside, и breakAfter
    overflow: scroll (для отображения в контейнере полос прокрутки) overflow

    Соответствующую документацию можно найти на странице "Многоколоночный макет" (http://msdn.microsoft.com/library/windows/apps/hh441204.aspx).

    Blend предоставляет отличное окружение для того, чтобы увидеть, как работают эти стили. Если вы размещаете мнокоголоночный элемент внутри ячейки сетки, которая может менять размер, вы можете задать параметр column-width и позволить подсистеме макетов добавлять и удалять колонки при необходимости, или вы можете использовать медиа-запросы или JavaScript для самостоятельной установки свойства column-count.

    Многоколоночная верстка CSS3, опять же, может быть применена лишь к содержимому одного отдельного элемента. Будучи весьма полезной, она имеет ограничения на использование прямоугольных элементов-контейнеров и прямоугольных колонок (увеличение их числа происходит в бок). Определенные приложения, наподобие электронных журналов, нуждаются в большей гибкости, в такой, как перетекание содержимого между несколькими элементами с более разнообразной формой, и в колонках, которые имеют смещение относительно друг друга. Эти взаимоотношения показаны на Рис. 6.8, где прямоугольник в левой верхней части может быть заголовком, блок-вставка может содержать изображение, и текстовое содержимое распределено между двумя колонками неправильной формы.

    (рис 6.8) Использование областей CSS для создания более сложных макетов с текстовыми колонками неправильной формы

    Для поддержки колонок неправильной формы, области CSS (CSS Regions) (http://dev.w3.org/csswg/css3-regions/) приходят в онлайн и поддерживаются приложениями для Магазина Windows (смотрите материал "Области" (http://msdn.microsoft.com/library/windows/apps/hh453722.aspx)). Области позволяют произвольно (это так - абсолютно) позиционировать элементы для взаимодействия со встроенным содержимым. На Рис. 6.8 изображение может быть позиционировано с использованием абсолютных параметров на странице и содержимое колонок будет его обтекать.

    Ключевый стиль для позиционирования элемента это float: -ms-positioned, который следует сопровождать position: absolute. Обычно это всё, что вам нужно: разместить в нужном месте позиционированный элемент, а подсистема макета сделает всё остальне. Следует отметить, что CSS-перенос (Hyphenation), еще один модуль, близко связан со всем этим, так как выполняет динамическое макетирование текста, мгновенно предоставляя подобные возможности. К счастью, приложения для Магазина Windows поддерживают -ms-hyphens и стили -ms-hyphenation* (их эквивалентные им свойства JavaScript). Переносы описаны в http://www.w3.org/TR/css3-text/, документацию, относящуюся к приложениям для Магазина Windows можно найти в материале "Области" (http://msdn.microsoft.com/library/windows/apps/hh453722.aspx).

    Вторая часть рассказа касается так называемых цепочек потоков или областей (которые, так же, являются частью спецификации, касающейся областей). Они обеспечивают возможность перетекания содержимого между множеством элементов-контейнеров, как показано на Рис. 6.9. Цепочки областей могут так же позволить стилизовать содержимое в соответствии со стилем контейнера, вместо того, чтобы стилизовать их так, как задано в их источнике. Каждый контейнер, другими словами, может задать собственный стиль и содержимое адаптируется к нему, но обычно, для обеспечения единообразия, все контейнеры имеют похожие стили.

    (рис 6.9) Цепочка CSS-областей позволяет содержимому перетекать между множеством элементов

    Всё это работает следующим образом. Источник контента определяет элемент iframe, который указывает на HTML-файл (и iframe, конечно, может принадлежать и локальному и веб-контексту). Он стилизуется с помощью ms-flow-into: <element> (в JavaScript - msFlowInfo), где <element> - это id первого контейнера:

    <!-- HTML -->	
    <iframe id="s1-content-source" src="/html/content.html"></iframe>
    <div class="s1-container"></div>	
    <div class="s1-container"></div>	
    <div class="s1-container"></div>	
    
    /* CSS */
    #s1-content-source {
    -ms-flow-into: content;
    }

    Обратите внимание на то, что -ms-flow-into предотвращает отображение содержимого лишь в iframe.

    Контейнером может быть любой незаменяемый (nonreplaced) элемент. То есть, любой элемент, внешний вид и размеры которого не определяются внешним источником, такой, как img. Он должен поддерживать включение содержимого между его открывающим и закрывающим тегами, наподобие div (он используется чаще всего), или p. Каждый контейнер стилизуется с помощью -ms-flow-from: <element> (msFlowFrom в JavaScript), где <element> - это первый контейнер в потоке. Расположение содержимого затем производится в том порядке, в котором элементы появляются в HTML (как выше):

    .s1-container {
    -ms-flow-from: content;
    /* Другие стили */
    }

    Этот простой пример взят из примера "Статические области CSS" (http://code.msdn.microsoft.com/windowsapps/Static-Regions-sample-f2158049), который так же содержит несколько других сценариев. Есть еще два интересных проекта, пример "Динамические области CSS" (http://code.msdn.microsoft.com/windowsapps/Dynamic-Region-Templates-94bc9c95), и "Шаблоны динамических областей CSS" (http://code.msdn.microsoft.com/windowsapps/Dynamic-Region-Templates-94bc9c95), последний является источником рисунка 6.8. Во всех этих случаях знайте, что стилизация областей ограничена свойствами, которые воздействуют на контейнер, но не на содержимое. Стиль содержимого взят из HTML-источника iframe. Именно поэтому text-overflow: ellipsis не работает, так же не работает font-color и так далее. Но стили, наподобие height и width, вместе со стилями границ, полей, отступов и другие свойства, которые не влияют на содержимое, применять можно.

    Что мы только что изучили

  • Макеты, которые соответствуют принципам дизайна Windows 8, а в особенности - общему стилю и типографике - помогают пользователям без промедления концентрироваться на содержимом вместо того, чтобы заниматься изучением особенностей приложений.
  • Принцип "прежде всего содержимое, и лишь затем внешнее оформление" позволяет содержимому использовать 75% пространства дисплея или даже больше, вместо 25%, что обычно для настольных и веб-приложений, уделяющих большое внимание внешнему оформлению.
  • В некоторых случаях, в таких, как создание домашней страницы или хаба приложения с различным содержимым, не поступающим из какой-то одной коллекции, лучше использовать обычный HTML/CSS макет вместо использования элемента управления.
  • Сдвигаемые HTML-области могут использовать точки прикрепления для автоматической остановки сдвига на определенных позициях внутри содержимого.
  • CSS-сетка - это весьма удобный механизм для создания адаптивных макетов уровня страницы, его можно использовать и во встроенном варианте. Гибкое окно CSS особенно удобно для встроенного содержимого, хотя его можно использовать и на уровне страницы, например, для центровки содержимого горизонтально и вертикально.
  • Каждая страница приложения (включая расширенный экран-заставку) может встретиться со всеми четырьмя режимами просмотра, поэтому дизайн приложения должен показывать, как обрабатываются все эти состояния. Медиа-запросы и API Media Query Listener можно использовать для обработки изменений состояния просмотра как декларативно, так и программно.
  • Приложения могут задавать предпочтительную ориентацию в манифесте и блокировать смену ориентации во время выполнения.
  • Событие window.onresize лучше всего позволяет узнать, когда изменился размер окна, что может быть обусловлено изменением состояния просмотра и/или изменением размера экрана и плотности пикселей.
  • Поддержка различных размеров экрана реализуется посредством адаптивных макетов, основанных на сетке или фиксированных макетов, использующих элемент управления WinJS.UI.ViewBox, который выполняет автоматическое масштабирование своего содержимого.
  • Основное условие, касающееся работы с экранами, поддерживающими различную плотность пикселей, заключается в использовании графических элементов, которые хорошо масштабируются. Это означает либо использование векторных изображений, либо предоставление масштабированных вариантов каждого из растровых изображений.
  • Приложения для Магазина Windows могут использовать возможности большого количества средств CSS, в том числе - сетки, гибкого окна, трансформации, многоколоночного текста и областей.
  • Вернуться к учебному плану