Статьи

Перезагружен API ориентации экрана

В сентябре я опубликовал статью под названием « Представление API ориентации экрана», в которой, что неудивительно, обсуждался API ориентации экрана. Этот API-интерфейс предоставляет возможность считывать состояние ориентации экрана, получать информацию об изменении этого состояния и иметь возможность привязывать ориентацию экрана к определенному состоянию. Как я уже упоминал в статье, интерфейс Screen Orientation находится на очень ранней стадии, так как это рабочий проект W3C. Текущие спецификации могут быть заменены через несколько месяцев более новой версией . Угадай, что? Это произошло! Фактически, последние версии Chrome (38) и Opera (25) поддерживают новую версию спецификаций (Firefox до 33 все еще поддерживает старую).

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

Что такое API ориентации экрана?

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

Если вы являетесь подписчиком моих статей и помните предыдущую статью об этом API, извините, что сообщаю вам, что только общие понятия совпадают и что почти все изменилось. В частности, все методы, свойства и события были перемещены в новый объект и / или переименованы. Не пугайтесь, я объясню все, что вам нужно.

свойства

В предыдущей версии API был доступен через свойство window.screen . Новая версия переместила все это в свойство orientation которое принадлежит window.screen . В текущей версии orientation — это объект, а не свойство, которое вернуло ориентацию устройства, какой оно было раньше.

Это свойство содержит следующие свойства только для чтения:

  • type : строка, содержащая текущую ориентацию устройства (подробнее о его возможных значениях в данный момент).
  • angle : число, указывающее текущий угол ориентации устройства.

type может принимать одно из следующих значений:

  • portrait-primary : ориентация в основном режиме портрета. Для смартфона это значение означает, что он находится в вертикальном положении с кнопками внизу.
  • portrait-secondary : ориентация в режиме вторичного портрета. Для смартфона это значение означает, что он находится в вертикальном положении с кнопками сверху (устройство внизу)
  • landscape-primary : ориентация в основном режиме ландшафта. Для смартфона это значение означает, что он находится в горизонтальном положении с кнопками справа.
  • landscape-secondary : ориентация в дополнительном ландшафтном режиме. Для смартфона это значение означает, что он находится в горизонтальном положении с кнопками слева.

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

методы

В предыдущих спецификациях у нас были lockOrientation() и unlockOrientation() . В новом они были переименованы как lock() и unlock() соответственно. Не удивительно, что они выполняют те же действия. lock() блокирует экран устройства в одной или нескольких ориентациях (в зависимости от параметра), а unlock() разблокирует экран.

Пример использования этих двух методов показан ниже:

 // Lock the screen in landscape-primary mode screen.orientation.lock('landscape-primary'); // Unlock the screen screen.orientation.unlock(); 

Результат вызова первого оператора этого фрагмента показан на рисунке ниже:

API ориентации устройства в действии
API Ориентация экрана в действии. Устройство физически находится в портретном режиме, но экран работает так, как если бы он был в альбомной ориентации.

Метод lock() сильно изменен, поэтому, пожалуйста, прочитайте внимательно. Он принимает только одну строку для указания ориентации, в которой мы хотим заблокировать экран, и возвращаемое значение больше не является логическим значением, а является объектом Promise . Если вам нужно введение в обещания JavaScript, SitePoint предоставит вам Обзор обещаний JavaScript . Наконец, есть два новых возможных значения, которые вы можете передать блокировке: any и natural . Полный список значений, которые вы можете передать, описан ниже:

  • any : устройства могут быть заблокированы в любой ориентации, которую они могут принять. Фактическая ориентация зависит от устройства, например, Samsung Galaxy S3 не может быть заблокирован в портретном режиме (вверх ногами).
  • natural : устройство находится в своей естественной ориентации. Для смартфона это обычно означает его основной портретный режим (с кнопками в направлении земли).
  • portrait-primary : ориентация в основном режиме портрета. Для смартфона это значение означает, что он находится в вертикальном положении с кнопками внизу.
  • portrait-secondary : ориентация в режиме вторичного портрета. Для смартфона это значение означает, что он находится в вертикальном положении с кнопками сверху (устройство внизу)
  • landscape-primary : ориентация в основном режиме ландшафта. Для смартфона это значение означает, что он находится в горизонтальном положении с кнопками справа.
  • landscape-secondary : ориентация в дополнительном ландшафтном режиме. Для смартфона это значение означает, что он находится в горизонтальном положении с кнопками слева.

Метод unlock() используется для снятия ранее установленной блокировки и не изменяется по сравнению с предыдущей версией.

События

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

 window.screen.orientation.addEventListener('change', function() { // do something here... }); 

Совместимость браузера

Поддержка API ориентации экрана улучшена с прошлого месяца с выпуском Chrome 38 и Opera 25. На сегодняшний день Chrome 38 и Opera 25 реализовали новую версию этого API без префикса производителя только в своей мобильной версии: Chrome для Android и Опера для Android. Firefox до версии 33 (последняя на момент написания этой статьи) поддерживает старую версию спецификаций, используя префикс своего поставщика ( moz ). Internet Explorer 11 также поддерживает старую версию с использованием префикса поставщика ( ms ).

Обратите внимание, что в данный момент Firefox выявляет две проблемы, которые вызывают сбой браузера. Вы можете найти больше информации на https://bugzil.la/1061372 и https://bugzil.la/1061373 .

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

 var orientation = screen.orientation || screen.mozOrientation || screen.msOrientation || null; if (orientation === null) { // API not supported } else if (typeof orientation === 'object') { // new versions supported } else { // old versions supported } 

демонстрация

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

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

Вы можете найти полный код для демонстрации ниже, но вы также можете играть с ним онлайн .

 <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta name="author" content> <title>Screen Orientation API Demo by Aurelio De Rosa</title> <style> * { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } body { max-width: 500px; margin: 2em auto; padding: 0 0.5em; font-size: 20px; } h1 { text-align: center; } .api-support { display: block; } .hidden { display: none; } .value { font-weight: bold; } .button-demo { padding: 0.5em; margin: 1em; } .author { display: block; margin-top: 1em; } </style> </head> <body> <h1>Screen Orientation API</h1> <span id="so-unsupported" class="api-support hidden">API not supported</span> <span id="soo-supported" class="api-support hidden">Old API version supported</span> <div id="so-results"> <ul> <li> The orientation of the device is <span id="orientation" class="value">unavailable</span>. </li> <li class="new-api hidden"> The angle of the device is <span id="angle" class="value">unavailable</span>. </li> </ul> <form> <label for="orientation-type">Lock the device in:</label> <select id="orientation-type"> <option value="any">any</option> <option value="natural">natural</option> <option value="portrait">portrait</option> <option value="landscape">landscape</option> <option value="portrait-primary">portrait-primary</option> <option value="portrait-secondary">portrait-secondary</option> <option value="landscape-primary">landscape-primary</option> <option value="landscape-secondary">landscape-secondary</option> </select> <br /> <input class="button-demo" id="lock-button" type="submit" value="Lock!" /> <input class="button-demo" id="unlock-button" type="reset" value="Unlock!" /> </form> </div> <small class="author"> Demo created by <a href="http://www.audero.it">Aurelio De Rosa</a> (<a href="https://twitter.com/AurelioDeRosa">@AurelioDeRosa</a>).<br /> This demo is part of the <a href="https://github.com/AurelioDeRosa/HTML5-API-demos">HTML5 API demos repository</a>. </small> <script> var prefix = 'orientation' in screen ? '' : 'mozOrientation' in screen ? 'moz' : 'msOrientation' in screen ? 'ms' : null; if (prefix === null) { document.getElementById('so-unsupported').classList.remove('hidden'); ['lock-button', 'unlock-button'].forEach(function(elementId) { document.getElementById(elementId).setAttribute('disabled', 'disabled'); }); } else { var select = document.getElementById('orientation-type'); var orientationElem = document.getElementById('orientation'); var onChangeHandler; var Fullscreen = { launch: function(element) { if(element.requestFullscreen) { element.requestFullscreen(); } else if(element.mozRequestFullScreen) { element.mozRequestFullScreen(); } else if(element.webkitRequestFullscreen) { element.webkitRequestFullscreen(); } else if(element.msRequestFullscreen) { element.msRequestFullscreen(); } }, exit: function() { if(document.exitFullscreen) { document.exitFullscreen(); } else if(document.mozCancelFullScreen) { document.mozCancelFullScreen(); } else if(document.webkitExitFullscreen) { document.webkitExitFullscreen(); } else if (document.msExitFullscreen) { document.msExitFullscreen(); } } }; // Determine what version of the API is implemented if ('orientation' in screen && 'angle' in screen.orientation) { // The browser supports the new version of the API // Show the properties supported by the new version var newProperties = document.getElementsByClassName('new-api'); for(var i = 0; i < newProperties.length; i++) { newProperties[i].classList.remove('hidden'); } document.getElementById('lock-button').addEventListener('click', function (event) { event.preventDefault(); Fullscreen.launch(document.documentElement); screen.orientation.lock(select.value); }); document.getElementById('unlock-button').addEventListener('click', function (event) { event.preventDefault(); Fullscreen.exit(); screen.orientation.unlock(); }); var angleElem = document.getElementById('angle'); onChangeHandler = function() { orientationElem.textContent = screen.orientation.type; angleElem.textContent = screen.orientation.angle; }; screen.orientation.addEventListener('change', onChangeHandler); onChangeHandler(); } else { // The browser supports the old version of the API, so the user is informed of that document.getElementById('soo-supported').classList.remove('hidden'); // Remove the options that aren't available in the old version of the API var unavailableOptions = [ document.querySelector('#orientation-type option[value="any"]'), document.querySelector('#orientation-type option[value="natural"]') ]; for(var i = 0; i < unavailableOptions.length; i++) { unavailableOptions[i].parentElement.removeChild(unavailableOptions[i]); } document.getElementById('lock-button').addEventListener('click', function (event) { event.preventDefault(); Fullscreen.launch(document.documentElement); setTimeout(function () { screen[prefix + (prefix === '' ? 'l' : 'L') + 'ockOrientation'](select.value); }, 1); }); document.getElementById('unlock-button').addEventListener('click', function (event) { event.preventDefault(); screen[prefix + (prefix === '' ? 'u' : 'U') + 'nlockOrientation'](); Fullscreen.exit(); }); onChangeHandler = function() { var orientationProperty = prefix + (prefix === '' ? 'o' : 'O') + 'rientation'; orientationElem.textContent = screen[orientationProperty]; }; screen.addEventListener(prefix + 'orientationchange', onChangeHandler); onChangeHandler(); } } </script> </body> </html> при <!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"/> <meta name="author" content> <title>Screen Orientation API Demo by Aurelio De Rosa</title> <style> * { -webkit-box-sizing: border-box; -moz-box-sizing: border-box; box-sizing: border-box; } body { max-width: 500px; margin: 2em auto; padding: 0 0.5em; font-size: 20px; } h1 { text-align: center; } .api-support { display: block; } .hidden { display: none; } .value { font-weight: bold; } .button-demo { padding: 0.5em; margin: 1em; } .author { display: block; margin-top: 1em; } </style> </head> <body> <h1>Screen Orientation API</h1> <span id="so-unsupported" class="api-support hidden">API not supported</span> <span id="soo-supported" class="api-support hidden">Old API version supported</span> <div id="so-results"> <ul> <li> The orientation of the device is <span id="orientation" class="value">unavailable</span>. </li> <li class="new-api hidden"> The angle of the device is <span id="angle" class="value">unavailable</span>. </li> </ul> <form> <label for="orientation-type">Lock the device in:</label> <select id="orientation-type"> <option value="any">any</option> <option value="natural">natural</option> <option value="portrait">portrait</option> <option value="landscape">landscape</option> <option value="portrait-primary">portrait-primary</option> <option value="portrait-secondary">portrait-secondary</option> <option value="landscape-primary">landscape-primary</option> <option value="landscape-secondary">landscape-secondary</option> </select> <br /> <input class="button-demo" id="lock-button" type="submit" value="Lock!" /> <input class="button-demo" id="unlock-button" type="reset" value="Unlock!" /> </form> </div> <small class="author"> Demo created by <a href="http://www.audero.it">Aurelio De Rosa</a> (<a href="https://twitter.com/AurelioDeRosa">@AurelioDeRosa</a>).<br /> This demo is part of the <a href="https://github.com/AurelioDeRosa/HTML5-API-demos">HTML5 API demos repository</a>. </small> <script> var prefix = 'orientation' in screen ? '' : 'mozOrientation' in screen ? 'moz' : 'msOrientation' in screen ? 'ms' : null; if (prefix === null) { document.getElementById('so-unsupported').classList.remove('hidden'); ['lock-button', 'unlock-button'].forEach(function(elementId) { document.getElementById(elementId).setAttribute('disabled', 'disabled'); }); } else { var select = document.getElementById('orientation-type'); var orientationElem = document.getElementById('orientation'); var onChangeHandler; var Fullscreen = { launch: function(element) { if(element.requestFullscreen) { element.requestFullscreen(); } else if(element.mozRequestFullScreen) { element.mozRequestFullScreen(); } else if(element.webkitRequestFullscreen) { element.webkitRequestFullscreen(); } else if(element.msRequestFullscreen) { element.msRequestFullscreen(); } }, exit: function() { if(document.exitFullscreen) { document.exitFullscreen(); } else if(document.mozCancelFullScreen) { document.mozCancelFullScreen(); } else if(document.webkitExitFullscreen) { document.webkitExitFullscreen(); } else if (document.msExitFullscreen) { document.msExitFullscreen(); } } }; // Determine what version of the API is implemented if ('orientation' in screen && 'angle' in screen.orientation) { // The browser supports the new version of the API // Show the properties supported by the new version var newProperties = document.getElementsByClassName('new-api'); for(var i = 0; i < newProperties.length; i++) { newProperties[i].classList.remove('hidden'); } document.getElementById('lock-button').addEventListener('click', function (event) { event.preventDefault(); Fullscreen.launch(document.documentElement); screen.orientation.lock(select.value); }); document.getElementById('unlock-button').addEventListener('click', function (event) { event.preventDefault(); Fullscreen.exit(); screen.orientation.unlock(); }); var angleElem = document.getElementById('angle'); onChangeHandler = function() { orientationElem.textContent = screen.orientation.type; angleElem.textContent = screen.orientation.angle; }; screen.orientation.addEventListener('change', onChangeHandler); onChangeHandler(); } else { // The browser supports the old version of the API, so the user is informed of that document.getElementById('soo-supported').classList.remove('hidden'); // Remove the options that aren't available in the old version of the API var unavailableOptions = [ document.querySelector('#orientation-type option[value="any"]'), document.querySelector('#orientation-type option[value="natural"]') ]; for(var i = 0; i < unavailableOptions.length; i++) { unavailableOptions[i].parentElement.removeChild(unavailableOptions[i]); } document.getElementById('lock-button').addEventListener('click', function (event) { event.preventDefault(); Fullscreen.launch(document.documentElement); setTimeout(function () { screen[prefix + (prefix === '' ? 'l' : 'L') + 'ockOrientation'](select.value); }, 1); }); document.getElementById('unlock-button').addEventListener('click', function (event) { event.preventDefault(); screen[prefix + (prefix === '' ? 'u' : 'U') + 'nlockOrientation'](); Fullscreen.exit(); }); onChangeHandler = function() { var orientationProperty = prefix + (prefix === '' ? 'o' : 'O') + 'rientation'; orientationElem.textContent = screen[orientationProperty]; }; screen.addEventListener(prefix + 'orientationchange', onChangeHandler); onChangeHandler(); } } </script> </body> </html> 

Вывод

В этой статье я описал новую версию спецификации Screen Orientation API. Этот API позволяет вам определять ориентацию устройства пользователя (с точки зрения портрета и ландшафта) и блокировать его в режиме, в котором нуждается ваше приложение. Как мы уже видели, поддержка возросла в последнее время, поэтому вы можете использовать ее в большем количестве браузеров, хотя вам следует обратить внимание на поддерживаемую версию API. Помните, что Chrome и Opera поддерживают новую версию, а Firefox и Internet Explorer поддерживают старую.