Использование датчика ориентации
Узнайте, как использовать датчики ориентации для определения ориентации устройства.
Важные API
Необходимые компоненты
Вы должны быть знакомы с языком разметки расширяемых приложений (XAML), Microsoft Visual C# и событиями.
Устройство или эмулятор, которые вы используете, должно поддерживать датчик ориентации.
Создание приложения OrientationSensor
Датчик ориентации — это один из нескольких типов датчиков окружающей среды, которые позволяют приложениям реагировать на изменения ориентации устройства.
Существует два различных типа API датчика ориентации, включенные в пространство имен Windows.Devices.Sensor: OrientationSensor и SimpleOrientation. Хотя оба этих датчика являются датчиками ориентации, этот термин перегружен и они используются для очень разных целей. Однако, так как оба являются датчиками ориентации, они рассматриваются в этой статье.
API OrientationSensor используется для двух приложений 3-D, которые получают кватернион и матрицу поворота. Кватернион может быть наиболее легко понят как поворот точки [x,y,z] о произвольной оси (в отличие от матрицы поворота, которая представляет повороты вокруг трех осей). Математика за кватерниона довольно экзотическим в том, что она включает геометрические свойства сложных чисел и математических свойств мнимых чисел, но работа с ними проста, и платформы, такие как DirectX поддерживают их. Сложное трехмерное приложение может использовать датчик ориентации для настройки перспективы пользователя. Этот датчик объединяет входные данные из акселерометра, гирометра и компаса.
API SimpleOrientation используется для определения текущей ориентации устройства с точки зрения определений, таких как книжный вверх, книжный вниз, альбом слева и альбом справа. Он также может определить, является ли устройство лицом или лицом вниз. Вместо возврата свойств, таких как "книжный вверх" или "альбомный левый", этот датчик возвращает значение поворота: "Не вращалось", "Поворот90DegreesCounterclockwise" и т. д. В следующей таблице перечислены общие свойства ориентации с соответствующим чтением датчика.
Ориентация | Соответствующее чтение датчика |
---|---|
Портрет вверх | NotRotated |
Альбом слева | Смена 90DegreesCounterclockwise |
Портрет вниз | Повернутый180DegreesCounterclockwise |
Альбом справа | Смена 270DegreesCounterclockwise |
Примечание.
Более полную реализацию см. в следующем разделе:
Instructions
Создайте проект, выбрав пустое приложение (универсальное приложение Windows) из шаблонов проектов Visual C# .
Откройте файл MainPage.xaml.cs проекта и замените существующий код следующим.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Core;
using Windows.Devices.Sensors;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/p/?linkid=234238
namespace App1
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
private OrientationSensor _sensor;
private async void ReadingChanged(object sender, OrientationSensorReadingChangedEventArgs e)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
OrientationSensorReading reading = e.Reading;
// Quaternion values
txtQuaternionX.Text = String.Format("{0,8:0.00000}", reading.Quaternion.X);
txtQuaternionY.Text = String.Format("{0,8:0.00000}", reading.Quaternion.Y);
txtQuaternionZ.Text = String.Format("{0,8:0.00000}", reading.Quaternion.Z);
txtQuaternionW.Text = String.Format("{0,8:0.00000}", reading.Quaternion.W);
// Rotation Matrix values
txtM11.Text = String.Format("{0,8:0.00000}", reading.RotationMatrix.M11);
txtM12.Text = String.Format("{0,8:0.00000}", reading.RotationMatrix.M12);
txtM13.Text = String.Format("{0,8:0.00000}", reading.RotationMatrix.M13);
txtM21.Text = String.Format("{0,8:0.00000}", reading.RotationMatrix.M21);
txtM22.Text = String.Format("{0,8:0.00000}", reading.RotationMatrix.M22);
txtM23.Text = String.Format("{0,8:0.00000}", reading.RotationMatrix.M23);
txtM31.Text = String.Format("{0,8:0.00000}", reading.RotationMatrix.M31);
txtM32.Text = String.Format("{0,8:0.00000}", reading.RotationMatrix.M32);
txtM33.Text = String.Format("{0,8:0.00000}", reading.RotationMatrix.M33);
});
}
public MainPage()
{
this.InitializeComponent();
_sensor = OrientationSensor.GetDefault();
// Establish the report interval for all scenarios
uint minReportInterval = _sensor.MinimumReportInterval;
uint reportInterval = minReportInterval > 16 ? minReportInterval : 16;
_sensor.ReportInterval = reportInterval;
// Establish event handler
_sensor.ReadingChanged += new TypedEventHandler<OrientationSensor, OrientationSensorReadingChangedEventArgs>(ReadingChanged);
}
}
}
Вам потребуется переименовать пространство имен в предыдущем фрагменте кода с именем, которым вы предоставили проект. Например, если вы создали проект с именем OrientationSensorCS, замените namespace App1
его namespace OrientationSensorCS
.
- Откройте файл MainPage.xaml и замените исходное содержимое следующим XML.
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid x:Name="LayoutRoot" Background="Black">
<TextBlock HorizontalAlignment="Left" Height="28" Margin="4,4,0,0" TextWrapping="Wrap" Text="M11:" VerticalAlignment="Top" Width="46"/>
<TextBlock HorizontalAlignment="Left" Height="23" Margin="4,36,0,0" TextWrapping="Wrap" Text="M12:" VerticalAlignment="Top" Width="39"/>
<TextBlock HorizontalAlignment="Left" Height="24" Margin="4,72,0,0" TextWrapping="Wrap" Text="M13:" VerticalAlignment="Top" Width="39"/>
<TextBlock HorizontalAlignment="Left" Height="31" Margin="4,118,0,0" TextWrapping="Wrap" Text="M21:" VerticalAlignment="Top" Width="39"/>
<TextBlock HorizontalAlignment="Left" Height="24" Margin="4,160,0,0" TextWrapping="Wrap" Text="M22:" VerticalAlignment="Top" Width="39"/>
<TextBlock HorizontalAlignment="Left" Height="24" Margin="8,201,0,0" TextWrapping="Wrap" Text="M23:" VerticalAlignment="Top" Width="35"/>
<TextBlock HorizontalAlignment="Left" Height="23" Margin="4,234,0,0" TextWrapping="Wrap" Text="M31:" VerticalAlignment="Top" Width="39"/>
<TextBlock HorizontalAlignment="Left" Height="28" Margin="4,274,0,0" TextWrapping="Wrap" Text="M32:" VerticalAlignment="Top" Width="46"/>
<TextBlock HorizontalAlignment="Left" Height="21" Margin="4,322,0,0" TextWrapping="Wrap" Text="M33:" VerticalAlignment="Top" Width="39"/>
<TextBlock x:Name="txtM11" HorizontalAlignment="Left" Height="19" Margin="43,4,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="53"/>
<TextBlock x:Name="txtM12" HorizontalAlignment="Left" Height="23" Margin="43,36,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="53"/>
<TextBlock x:Name="txtM13" HorizontalAlignment="Left" Height="15" Margin="43,72,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="53"/>
<TextBlock x:Name="txtM21" HorizontalAlignment="Left" Height="20" Margin="43,114,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="53"/>
<TextBlock x:Name="txtM22" HorizontalAlignment="Left" Height="19" Margin="43,156,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="53"/>
<TextBlock x:Name="txtM23" HorizontalAlignment="Left" Height="16" Margin="43,197,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="53"/>
<TextBlock x:Name="txtM31" HorizontalAlignment="Left" Height="17" Margin="43,230,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="53"/>
<TextBlock x:Name="txtM32" HorizontalAlignment="Left" Height="19" Margin="43,270,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="53"/>
<TextBlock x:Name="txtM33" HorizontalAlignment="Left" Height="21" Margin="43,322,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="53"/>
<TextBlock HorizontalAlignment="Left" Height="15" Margin="194,8,0,0" TextWrapping="Wrap" Text="Quaternion X:" VerticalAlignment="Top" Width="81"/>
<TextBlock HorizontalAlignment="Left" Height="23" Margin="194,36,0,0" TextWrapping="Wrap" Text="Quaternion Y:" VerticalAlignment="Top" Width="81"/>
<TextBlock HorizontalAlignment="Left" Height="15" Margin="194,72,0,0" TextWrapping="Wrap" Text="Quaternion Z:" VerticalAlignment="Top" Width="81"/>
<TextBlock x:Name="txtQuaternionX" HorizontalAlignment="Left" Height="15" Margin="279,8,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="104"/>
<TextBlock x:Name="txtQuaternionY" HorizontalAlignment="Left" Height="12" Margin="275,36,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="108"/>
<TextBlock x:Name="txtQuaternionZ" HorizontalAlignment="Left" Height="19" Margin="275,68,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="89"/>
<TextBlock HorizontalAlignment="Left" Height="21" Margin="194,96,0,0" TextWrapping="Wrap" Text="Quaternion W:" VerticalAlignment="Top" Width="81"/>
<TextBlock x:Name="txtQuaternionW" HorizontalAlignment="Left" Height="12" Margin="279,96,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="72"/>
</Grid>
</Page>
Необходимо заменить первую часть имени класса в предыдущем фрагменте на пространство имен приложения. Например, если вы создали проект с именем OrientationSensorCS, замените x:Class="App1.MainPage"
его x:Class="OrientationSensorCS.MainPage"
. Также следует заменить xmlns:local="using:App1"
xmlns:local="using:OrientationSensorCS"
на .
- Нажмите клавишу F5 или выберите отладку отладки для>сборки, развертывания и запуска приложения.
После запуска приложения можно изменить ориентацию, переместив устройство или используя средства эмулятора.
- Остановите приложение, вернитесь в Visual Studio и нажав клавиши SHIFT+F5 или выберите "Остановить отладку отладки>", чтобы остановить приложение.
Описание
В предыдущем примере показано, как мало кода необходимо написать, чтобы интегрировать входные данные датчика ориентации в приложение.
Приложение устанавливает соединение с датчиком ориентации по умолчанию в методе MainPage .
_sensor = OrientationSensor.GetDefault();
Приложение устанавливает интервал отчета в методе MainPage . Этот код извлекает минимальный интервал, поддерживаемый устройством, и сравнивает его с запрошенным интервалом в 16 миллисекунд (приблизительно 60-Гц скорость обновления). Если минимальный поддерживаемый интервал больше запрошенного интервала, код задает значение минимальному. В противном случае оно задает значение запрошенного интервала.
uint minReportInterval = _sensor.MinimumReportInterval;
uint reportInterval = minReportInterval > 16 ? minReportInterval : 16;
_sensor.ReportInterval = reportInterval;
Новые данные датчика записываются в методе ReadingChanged . Каждый раз, когда драйвер датчика получает новые данные от датчика, он передает значения приложению с помощью этого обработчика событий. Приложение регистрирует этот обработчик событий в следующей строке.
_sensor.ReadingChanged += new TypedEventHandler<OrientationSensor,
OrientationSensorReadingChangedEventArgs>(ReadingChanged);
Эти новые значения записываются в TextBlocks, найденные в XAML проекта.
Создание приложения SimpleOrientation
Этот раздел разделен на два подраздела. Первый подраздел поможет вам выполнить действия, необходимые для создания простого приложения ориентации с нуля. В следующем подразделе объясняется, что только что созданное приложение.
Instructions
Создайте проект, выбрав пустое приложение (универсальное приложение Windows) из шаблонов проектов Visual C# .
Откройте файл MainPage.xaml.cs проекта и замените существующий код следующим.
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using Windows.Foundation;
using Windows.Foundation.Collections;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Controls.Primitives;
using Windows.UI.Xaml.Data;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
using Windows.UI.Xaml.Navigation;
using Windows.UI.Core;
using Windows.Devices.Sensors;
// The Blank Page item template is documented at https://go.microsoft.com/fwlink/p/?linkid=234238
namespace App1
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public sealed partial class MainPage : Page
{
// Sensor and dispatcher variables
private SimpleOrientationSensor _simpleorientation;
// This event handler writes the current sensor reading to
// a text block on the app' s main page.
private async void OrientationChanged(object sender, SimpleOrientationSensorOrientationChangedEventArgs e)
{
await Dispatcher.RunAsync(CoreDispatcherPriority.Normal, () =>
{
SimpleOrientation orientation = e.Orientation;
switch (orientation)
{
case SimpleOrientation.NotRotated:
txtOrientation.Text = "Not Rotated";
break;
case SimpleOrientation.Rotated90DegreesCounterclockwise:
txtOrientation.Text = "Rotated 90 Degrees Counterclockwise";
break;
case SimpleOrientation.Rotated180DegreesCounterclockwise:
txtOrientation.Text = "Rotated 180 Degrees Counterclockwise";
break;
case SimpleOrientation.Rotated270DegreesCounterclockwise:
txtOrientation.Text = "Rotated 270 Degrees Counterclockwise";
break;
case SimpleOrientation.Faceup:
txtOrientation.Text = "Faceup";
break;
case SimpleOrientation.Facedown:
txtOrientation.Text = "Facedown";
break;
default:
txtOrientation.Text = "Unknown orientation";
break;
}
});
}
public MainPage()
{
this.InitializeComponent();
_simpleorientation = SimpleOrientationSensor.GetDefault();
// Assign an event handler for the sensor orientation-changed event
if (_simpleorientation != null)
{
_simpleorientation.OrientationChanged += new TypedEventHandler<SimpleOrientationSensor, SimpleOrientationSensorOrientationChangedEventArgs>(OrientationChanged);
}
}
}
}
Вам потребуется переименовать пространство имен в предыдущем фрагменте кода с именем, которым вы предоставили проект. Например, если вы создали проект с именем SimpleOrientationCS, замените namespace App1
его namespace SimpleOrientationCS
.
- Откройте файл MainPage.xaml и замените исходное содержимое следующим XML.
<Page
x:Class="App1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App1"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d">
<Grid x:Name="LayoutRoot" Background="#FF0C0C0C">
<TextBlock HorizontalAlignment="Left" Height="24" Margin="8,8,0,0" TextWrapping="Wrap" Text="Current Orientation:" VerticalAlignment="Top" Width="101" Foreground="#FFF8F7F7"/>
<TextBlock x:Name="txtOrientation" HorizontalAlignment="Left" Height="24" Margin="118,8,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="175" Foreground="#FFFEFAFA"/>
</Grid>
</Page>
Необходимо заменить первую часть имени класса в предыдущем фрагменте на пространство имен приложения. Например, если вы создали проект с именем SimpleOrientationCS, замените x:Class="App1.MainPage"
его x:Class="SimpleOrientationCS.MainPage"
. Также следует заменить xmlns:local="using:App1"
xmlns:local="using:SimpleOrientationCS"
на .
- Нажмите клавишу F5 или выберите отладку отладки для>сборки, развертывания и запуска приложения.
После запуска приложения можно изменить ориентацию, переместив устройство или используя средства эмулятора.
- Остановите приложение, вернитесь в Visual Studio и нажав клавиши SHIFT+F5 или выберите "Остановить отладку отладки>", чтобы остановить приложение.
Описание
В предыдущем примере показано, насколько мало кода необходимо написать, чтобы интегрировать входные данные датчика простой ориентации в приложение.
Приложение устанавливает соединение с датчиком по умолчанию в методе MainPage .
_simpleorientation = SimpleOrientationSensor.GetDefault();
Новые данные датчика записываются в методе OrientationChanged . Каждый раз, когда драйвер датчика получает новые данные от датчика, он передает значения приложению с помощью этого обработчика событий. Приложение регистрирует этот обработчик событий в следующей строке.
_simpleorientation.OrientationChanged += new TypedEventHandler<SimpleOrientationSensor,
SimpleOrientationSensorOrientationChangedEventArgs>(OrientationChanged);
Эти новые значения записываются в TextBlock, найденный в XAML проекта.
<TextBlock HorizontalAlignment="Left" Height="24" Margin="8,8,0,0" TextWrapping="Wrap" Text="Current Orientation:" VerticalAlignment="Top" Width="101" Foreground="#FFF8F7F7"/>
<TextBlock x:Name="txtOrientation" HorizontalAlignment="Left" Height="24" Margin="118,8,0,0" TextWrapping="Wrap" Text="TextBlock" VerticalAlignment="Top" Width="175" Foreground="#FFFEFAFA"/>