传感器数据和显示方向 (HTML)

[ 本文适用于编写 Windows 运行时应用的 Windows 8.x 和 Windows Phone 8.x 开发人员。如果你要针对 Windows 10 进行开发,请参阅 最新文档 ]

来自 AccelerometerGyrometerCompassInclinometerOrientationSensor 类的传感器数据由其参考轴定义。 这些轴由设备的横向方向定义,并在用户转动设备时与其一起旋转。 如果你的应用支持自动旋转,即,如果它在用户旋转设备时自行重定向以适应设备,则必须先调整关于旋转的传感器数据才能使用它。

显示方向和设备方向

为了了解传感器的参考轴,你需要区分显示方向和设备方向。显示方向是方向文本且图像均显示在屏幕上,而设备方向则是设备的物理定位。在下图中,设备和显示方向都采用 Landscape

采用 Landscape 的显示和设备方向

下图显示了采用 LandscapeFlipped 的显示和设备方向。

显示和设备方向采用 LandscapeFlipped 的显示和设备方向

下一张图片显示了采用 Landscape 的显示方向和采用 LandscapeFlipped 的设备方向。

采用 Landscape 的显示方向和采用 LandscapeFlipped 的设备方向。

你可以使用具有 CurrentOrientation 属性的 GetForCurrentView 方法以通过 DisplayInformation 类查询方向值。然后,你可以通过与 DisplayOrientations 枚举进行比较来创建逻辑。 请记住,对于你支持的每一个方向,必须支持该方向的参考轴的转换。

优先横向设备和优先纵向设备

制造商现在正在生产优先横向设备和优先纵向设备。当制造商将组件集成到设备中时,他们采用统一且一致的方式执行此操作,以便所有设备均可在相同的参考帧中运行。 下表显示了适用于优先横向设备和优先纵向设备的传感器轴。

方向 优先横向 优先纵向

Landscape

采用 Landscape 方向的优先横向设备 采用 Landscape 方向的优先纵向设备

Portrait

采用 Portrait 方向的优先横向设备 采用 Portrait 方向的优先纵向设备

LandscapeFlipped

采用 LandscapeFlipped 方向的优先横向设备 采用 LandscapeFlipped 方向的优先纵向设备

PortraitFlipped

采用 PortraitFlipped 方向的优先横向设备 采用 PortraitFlipped 方向的优先纵向设备

 

显示方向和指南针方位

指南针方位具体取决于参考轴,因此它随设备方向发生变化。 可以基于此表进行修正(假设用户面朝北方)。

显示方向 用于指南针方位的参考轴 面朝北方时的 API 指南针方位 指南针方位修正

Landscape

-Z

0

方位

Portrait

Y

90

(方位 + 270)% 360

LandscapeFlipped

Z

180

(方位 + 180)% 360

PortraitFlipped

Y

270

(方位 + 90)% 360

 

修改指南针方位(如该表中所示),以便正确显示方位,如下所示。

function readingChanged(e) {
    var heading = e.reading.headingMagneticNorth;
    var displayOffset;

    // Calculate the compass heading offset based on
    // the current display orientation.
    var displayInfo = Windows.Graphics.Display.DisplayInformation.getForCurrentView();
    
    switch (displayInfo.currentOrientation) {
        case Windows.Graphics.Display.DisplayOrientations.landscape:
            displayOffset = 0;
            break;
        case Windows.Graphics.Display.DisplayOrientations.portrait:
            displayOffset = 270;
            break;
        case Windows.Graphics.Display.DisplayOrientations.landscapeFlipped:
            displayOffset = 180;
            break;
        case Windows.Graphics.Display.DisplayOrientations.portraitFlipped:
            displayOffset = 90;
            break;
     }

    var displayCompensatedHeading = (heading + displayOffset) % 360;

    // Update the UI...
}

使用加速度计和陀螺测试仪显示方向

此表可转换用于显示方向的加速度计和陀螺测试仪数据。

参考轴 X Y Z

Landscape

X

Y

Z

Portrait

Y

-X

Z

LandscapeFlipped

-X

-Y

Z

PortraitFlipped

-Y

X

Z

 

以下是可将这些转换应用到陀螺测试仪的代码示例。

function readingChanged(e) {
    var reading = e.reading;
    var displayOffset;

    // Calculate the gyrometer axes based on
    // the current display orientation.
    var displayInfo = Windows.Graphics.Display.DisplayInformation.getForCurrentView();
    switch (displayInfo.currentOrientation) {
        case Windows.Graphics.Display.DisplayOrientations.landscape: 
            x_Axis = reading.angularVelocityX;
            y_Axis = reading.angularVelocityY;
            z_Axis = reading.angularVelocityZ;
            break;
        case Windows.Graphics.Display.DisplayOrientations.portrait: 
            x_Axis = reading.angularVelocityY;
            y_Axis = -1 * reading.angularVelocityX;
            z_Axis = reading.angularVelocityZ;
            break; 
        case Windows.Graphics.Display.DisplayOrientations.landscapeFlipped: 
            x_Axis = -1 * reading.angularVelocityX;
            y_Axis = -1 * reading.angularVelocityY;
            z_Axis = reading.angularVelocityZ;
            break; 
        case Windows.Graphics.Display.DisplayOrientations.portraitFlipped: 
            x_Axis = -1 * reading.angularVelocityY;
            y_Axis = reading.angularVelocityX;
            z_Axis = reading.angularVelocityZ;
            break;
     }

    // Update the UI...
}

显示方向和设备方向

必须采用不同的方式更改 OrientationSensor。 请考虑逆时针旋转到 Z 轴时的不同方向,因此我们需要反向旋转以返回用户的方向。对于四元数数据,我们可以使用欧拉公式定义参考四元数的旋转,也可以使用参考旋转矩阵。

欧拉公式

若要获取所需的相对方向,请用参考对象乘以绝对对象。请注意,此数学算法不可应用交换律。

用参考对象乘以绝对对象

在之前的表达式中,绝对对象由传感器数据返回。

显示方向 围绕 Z 进行逆时针旋转 参考四元数(反向旋转) 参考旋转矩阵(反向旋转)

Landscape

0

1 + 0i + 0j + 0k

[1 0 0

0 1 0

0 0 1]

Portrait

90

cos(-45⁰) + (i + j + k)*sin(-45⁰)

[0 1 0

-1 0 0

0 0 1]

LandscapeFlipped

180

0 - i - j - k

[1 0 0

0 1 0

0 0 1]

PortraitFlipped

270

cos(-135⁰) + (i + j + k)*sin(-135⁰)

[0 -1 0

1 0 0

0 0 1]