html5 - 获取相对坐标中的设备方向旋转

2023-11-23

我正在尝试改变两者之间的方向deviceorientation沿左右轴和上下轴的事件,这些轴通常定义为电话x and y axis (https://developer.mozilla.org/en-US/docs/Web/Guide/Events/Orientation_and_motion_data_explained)

即在瞬间之间t1 and t2这些电话轴从哪里移动(x1, y1) to (x2, y2), 想要得到(angle(x2-x1), angle(y1-y2)).

当设备处于纵向模式(与横向模式相反)时,这些轴似乎对应于beta and gamma。然而,当手机垂直(底部面向地面)时,gamma值变得极其不稳定,从90度跳到-90度(同时,alpha跳了180度)你可以很容易地看到在你的手机上

我想避免这种情况,并获得 360 范围内的值。这是我到目前为止所拥有的:

// assuming portrait mode
var beta0, gamma0;
window.addEventListener('deviceorientation', function(orientation) {
  if (typeof beta0 === 'undefined') {
    beta0 = beta;
    gamma0 = gamma;
  } 

  console.log('user has moved to the left by', gamma - gamma0, ' and to the top by', beta - beta0);
});

当设备大部分水平时,这可以正常工作,而当设备是垂直时,则根本不起作用


好的。首先简单解释一下设备方向输入:

绝对坐标系,(X, Y, Z)是这样的X是东方,Y是北和Z起来了。设备相对坐标系,(x, y, z)是这样的x是对的,y是顶部并且z起来了。然后是方向角,(alpha, beta, gamma)是描述连续变化的三个简单旋转的角度(X, Y, Z) to (x, y, z) as so:

  • 旋转Z by alpha度,这会改变(X, Y, Z) to (X', Y', Z') with Z' = Z
  • 旋转X' by beta度,这会改变(X', Y', Z') to (X'', Y'', Z'') with X'' = X'
  • 旋转Y'' by gamma度,这会改变(X'', Y'', Z'') to (x, y, z) with y = Y''

(它们被称为类型的固有泰特-布赖恩角Z-X'-Y'')

现在我们可以通过组成简单的旋转矩阵来得到相应的旋转矩阵,每个旋转矩阵对应于三个旋转之一。

                                 [   cC   0    sC  ] [  1    0    0   ] [  cA   -sA  0  ]
R(A, B, C) = Ry(C)*Rx(B)*Rz(A) = |   0    1    0   |*|  0    cB  -sB  |*[  sA   cA   0  ]
                                 [  -sC   0    cC  ] [  0    sB   cB  ] [  0    0    1  ]

where A, B, C是缩写alpha, beta, gamma and s, c for sin, cos.

现在,我们感兴趣的是左右的角度(y轴)和自上而下(xaxis) 两个位置之间的旋转增量(x, y, z) and (x', y', z')对应于方向(A, B, C) and (A', B', C')

的坐标(x', y', z')在...方面(x, y, z)由以下给出R(A', B', C') * R(A, B, C)^-1 = R(A', B', C') * R(A, B, C)^T因为逆矩阵是正交(旋转)矩阵的转置。最后,如果z' = p*x + q*y + r*z,这些旋转的角度是p绕左右轴并且q围绕自上而下的角度(这对于小角度来说是正确的,假设频繁的方向更新,否则asin(p) and asin(r)更接近事实)

下面是一些获取旋转矩阵的 JavaScript:

/*
 * gl-matrix is a nice library that handles rotation stuff efficiently
 * The 3x3 matrix is a 9 element array
 * such that indexes 0-2 correspond to the first column, 3-5 to the second column and 6-8 to the third
 */
import {mat3} from 'gl-matrix';

let _x, _y, _z;
let cX, cY, cZ, sX, sY, sZ;
/*
 * return the rotation matrix corresponding to the orientation angles
 */
const fromOrientation = function(out, alpha, beta, gamma) {
  _z = alpha;
  _x = beta;
  _y = gamma;

  cX = Math.cos( _x );
  cY = Math.cos( _y );
  cZ = Math.cos( _z );
  sX = Math.sin( _x );
  sY = Math.sin( _y );
  sZ = Math.sin( _z );

  out[0] = cZ * cY + sZ * sX * sY,    // row 1, col 1
  out[1] = cX * sZ,                   // row 2, col 1
  out[2] = - cZ * sY + sZ * sX * cY , // row 3, col 1

  out[3] = - cY * sZ + cZ * sX * sY,  // row 1, col 2
  out[4] = cZ * cX,                   // row 2, col 2
  out[5] = sZ * sY + cZ * cY * sX,    // row 3, col 2

  out[6] = cX * sY,                   // row 1, col 3
  out[7] = - sX,                      // row 2, col 3
  out[8] = cX * cY                    // row 3, col 3
};

现在我们得到角度增量:

const deg2rad = Math.PI / 180; // Degree-to-Radian conversion
let currentRotMat, previousRotMat, inverseMat, relativeRotationDelta,
  totalRightAngularMovement=0, totalTopAngularMovement=0;

window.addEventListener('deviceorientation', ({alpha, beta, gamma}) => {
  // init values if necessary
  if (!previousRotMat) {
    previousRotMat = mat3.create();
    currentRotMat = mat3.create();
    relativeRotationDelta = mat3.create();

    fromOrientation(currentRotMat, alpha * deg2rad, beta * deg2rad, gamma * deg2rad);
  }

  // save last orientation
  mat3.copy(previousRotMat, currentRotMat);

  // get rotation in the previous orientation coordinate
  fromOrientation(currentRotMat, alpha * deg2rad, beta * deg2rad, gamma * deg2rad);
  mat3.transpose(inverseMat, previousRotMat); // for rotation matrix, inverse is transpose
  mat3.multiply(relativeRotationDelta, currentRotMat, inverseMat);

  // add the angular deltas to the cummulative rotation
  totalRightAngularMovement += Math.asin(relativeRotationDelta[6]) / deg2rad;
  totalTopAngularMovement += Math.asin(relativeRotationDelta[7]) / deg2rad;
}

最后,为了考虑屏幕方向,我们必须替换

  _z = alpha;
  _x = beta;
  _y = gamma;

by

const screen = window.screen;
const getScreenOrientation = () => {
  const oriented = screen && (screen.orientation || screen.mozOrientation);
  if (oriented) switch (oriented.type || oriented) {
    case 'landscape-primary':
      return 90;
    case 'landscape-secondary':
      return -90;
    case 'portrait-secondary':
      return 180;
    case 'portrait-primary':
      return 0;
  }
  return window.orientation|0; // defaults to zero if orientation is unsupported
};

const screenOrientation = getScreenOrientation();

_z = alpha;
if (screenOrientation === 90) {
  _x = - gamma;
  _y = beta;
}
else if (screenOrientation === -90) {
  _x = gamma;
  _y = - beta;
}
else if (screenOrientation === 180) {
  _x = - beta;
  _y = - gamma;
}
else if (screenOrientation === 0) {
  _x = beta;
  _y = gamma;
}

请注意,累积的左右角度和上下角度将取决于用户选择的路径,并且不能直接从设备方向推断,而是必须通过移动进行跟踪。您可以通过不同的动作到达相同的位置:

  • 方法一:

    • 保持手机水平并顺时针旋转 90 度。 (这既不是左右旋转,也不是上下旋转)
    • 将手机保持横向模式并向您旋转 90 度。 (这既不是左右90度旋转)
    • 将手机面向您并旋转 90 度,使其向上。 (这既不是左右90度旋转)
  • 方法2:

    • 将手机旋转 90 度,使其面向您且垂直(这是 90 度上下旋转)
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

html5 - 获取相对坐标中的设备方向旋转 的相关文章

  • 如何使用 JavaScript 获取元素的填充值?

    我有一个textarea在我的 HTML 中 我需要获取整数或浮点形式的填充数值 以像素为单位 我如何使用 JavaScript 获取它 我没有使用 jQuery 所以我正在寻找纯 JavaScript 解决方案 这将返回padding l
  • 不使用控件时,视频元素在 Chrome 中消失

    So I think这是一个浏览器错误 它出现在一个更复杂的设计 网站中 但我已经进行了很好的尝试 简化了我的代码和设计等 并发现了以下内容 嵌入时
  • 在webview android中加载本地html文件

    我正在尝试在 android 的 webview 中加载 html 文件的内容 但是 它给了我 网页不可用错误 如果我尝试使用谷歌或雅虎等网站 它们就会起作用 html文件位于src gt main gt assests gt index
  • AngularJS 在指令运行之前通过 AJAX 检索数据

    我正在使用 AngularUIuiMap http angular ui github com directives map实例化谷歌地图的指令 uiMap 指令非常适合处理硬编码数据 mapOptions and myMarkers 但是
  • 使用 VBA 通过 Access 导航网页/操作 IE

    你好 StackOverflow 社区 我有一个关于使用 Access VBA 操作 IE 的问题 本质上 我正在尝试编写代码 使用 IE 打开特定网页 在该页面中搜索特定链接 目标链接的名称将取决于用户的情况 通过以编程方式单击该链接导航
  • 如何设置 CSS 网格的最大高度

    我有以下 CSS 网格 grid 3x4 display grid grid template columns 1fr 1fr 1fr grid template rows 1fr 1fr 1fr 1fr grid template are
  • 应用旋转时,HTML5 canvas Clip() 在 Chrome 中不起作用

    我试图在画布上使用剪辑区域 一旦坐标系旋转任何非零值 它就会停止工作 window onload function var canvas document getElementById mainCanvas var ctx canvas g
  • 增加数字输入、CSS、HTML 上的向下和向上箭头的大小

    有没有办法利用CSS来增大数字输入框右侧的上下箭头的大小 只是向上和向下箭头 而不是整个输入框 或者至少是按比例的 看这个例子 size 36 font size 36px size 12 font size 12px
  • 如何将udp发送到udp node.js服务器?

    我对此很陌生 所以我真的不知道我在做什么 但我已经设置了一个 node js udp 服务器 我想从客户端 来自网站 向它发送一个数据包 但我不知道如何在 javascript 中做到这一点 或者是否可能 我不是在研究如何从 Node js
  • 来自 JSON 的 Angular 8 动态表单

    我正在尝试从 JSON 模式递归生成动态表单 但我正在努力解决找不到表单控件的问题 这是代码示例 我收到这个错误 错误错误 找不到名称为 createdAt 的控件 我尝试了不同的方法 但仍然存在问题 我知道我错过了一些东西 所以请帮忙 任
  • VBA / HTML / jQuery 选择自动完成 - 在列表中选择

    我正在尝试使用 Excel 中的 VBA 在网站的列表中选择一个值 这不是一个 正常列表 该网站使用 jQuery 选择自动完成 如下所示 example http davidwalsh name demo jquery chosen ph
  • HTML2canvas 和 Canvas2image,下载的屏幕截图不显示我的 HTML 图像

    我一直在开发一个 HTML 页面 我想将其转换为图像 我一直在使用 html2canvas 和 canvas2image 脚本并采用此代码http jsfiddle net 8ypxW 3 http jsfiddle net 8ypxW 3
  • 如何延迟加载嵌入在 iframe 上的 YouTube 视频?

    如何将延迟加载应用于iframe嵌入视频 我尝试添加loading eager loading auto and loading lazyload 您可以使用srcdoc你里面的属性iframe标签来加载图像 请参阅以下示例作为参考
  • 如何将送货地址复制到帐单地址

    我想知道是否可以将送货地址复制到帐单地址 当用户单击与送货地址相同的复选框时 送货地址值将被复制到账单输入字段 我完成了大部分部分 但我不确定如何将选择菜单 状态 值复制到帐单地址 我真的很感谢任何帮助 My code document r
  • 我可以停止 :hover 应用于元素吗?

    假设我有一些 CSS button hover font weight bold 我怎样才能防止 hover随意应用样式 我的目标用例是当元素被禁用时 例如 使用这个 HTML
  • JSTL 在循环中每 5 个字段集创建一个新行

    您好 我目前正在迭代并在表中显示字段集列表 为了让布局变得更得体一些 我想在每次循环到达第五个字段集时创建一个新行 谢谢 JSP div class det table class det tr td td tr table div
  • 悬停时为 SVG 制作动画

    我正在尝试在悬停时为 SVG 文件设置动画 默认情况下 它可以使用 svg 函数实现出色的动画效果 例如
  • 如何获取 UIWebView 中元素的位置?

    我在 iPad 程序中加载了 html 的 UIWebView 通过使用 webkit column width 我将 html 分为几列 padding 0px height 1024px webkit column gap 0px we
  • 单击引导分页链接时调用 jquery 函数

    我想在单击引导分页链接时调用 jquery 函数 假设我想从第1页遍历到第2页 应该调用一个jquery函数 我正在使用以下代码 但它不起作用 ul pagination on click li function alert page ch
  • 三级十进制有序列表 CSS

    我有一个 html 中的三级有序列表 我想为其提供如下样式 1 Item 1 1 1 Item 2 1 1 1 Item 3 下一个 plunker 中有一个 html 示例 http plnkr co edit DqhZ5pJILTUHG

随机推荐

  • 在gradle中重命名apk

    我想从 gradle 重命名我的 apk 我在构建中有以下几行 applicationVariants all variant gt def file variant outputFile def filename file name re
  • shared_ptr会自动释放内存吗?

    我需要在这里使用shared ptr 因为我无法更改API Foo1 foo1 new Foo1 shared ptr
  • Linux,spidev:为什么它不应该直接在设备树中?

    我想定义一个具有用户模式访问权限的 SPI 设备 如中所述http linux sunxi org SPIdev 按照这些示例 我在设备树中添加了以下内容 ecspi1 other stuff mydev 0 compatible spid
  • 在Go中用小RAM读取大文件的最快方法[关闭]

    Closed 这个问题需要多问focused 目前不接受答案 我想从不同的文本或JSON or CSV文件 我应该遵循哪种方法 我有博客文章文件读取 and 使用小 RAM 读取 2 GB 文本文件文件读取的不同方法 不同的方法 分块读取文
  • 将整数集转换为范围

    将一组整数转换为一组范围的最惯用的方法是什么 例如 给定集合 0 1 2 3 4 7 8 9 11 我想得到 0 4 7 9 11 11 假设我们正在转换std set
  • 如何在WPF中使用GDI+绘图?

    我想在我的 WPF 控件中使用 GDI 绘图 有多种方法可以做到这一点 最简单的方法是锁定使用 GDI 操作的位图 获取像素缓冲区 从锁定中获取的 BitmapData 中的 Scan0 IntPtr 复制内存 从你的像素缓冲区到Write
  • 如何在 bash 中传递完整的参数列表,同时将多字参数保存在一起?

    我在 bash 变量扩展中遇到一些分词问题 我希望能够将参数列表存储在变量中并运行它 但是任何引用的多字参数都不会按照我的预期进行评估 我将用一个例子来解释我的问题 假设我有一个函数decho将每个位置参数打印在它自己的行上 bin bas
  • 如何在 LaTeX 中发出参考文献的文本内容?

    我有一个部分 section Introduction label sec introduction 我想要一个指向该部分的链接 其中链接文本是该部分的名称 我可以用hyperref The hyperrf sec introduction
  • 为什么我不应该在 PHP 中使用 mysql_* 函数?

    想要改进这篇文章吗 提供此问题的详细答案 包括引用和解释为什么你的答案是正确的 不够详细的答案可能会被编辑或删除 不应该使用的技术原因是什么mysql 功能 例如 mysql query mysql connect or mysql rea
  • 如何在 C# 中使用正则表达式获取某个特定单词之前的数字?

    我们将使用下面的正则表达式来获取单词之前的数字 例子 838123 某个词 8 某个词 12 某个词 d s someWord 但有时数字和单词之间会出现任何内容 请参阅下面的示例行 Ex 43434 的 someword 12 任何 so
  • 如何检测 DataGridView 控件中的垂直滚动条

    在vs2008中使用winform 我有一个 DataGridView 我想检测垂直滚动条何时可见 我应该报名参加什么活动 我添加了网格最后一列中每个单元格值的求和 并在 DataGridView 底部的文本框中显示该值 我希望此文本框与单
  • 使用 Lua C API 迭代表中的表

    我正在尝试迭代 Lua 中的表并输出 每个表的键 每个表中每个条目的键 值对 这是代码 void print table lua State L lua pushnil L while lua next L 2 0 const char k
  • EXTJS 5:如何在 EXT JS 5 中对网格列进行排序

    我最近将 EXT JS 的版本更新到 5 并且 doSort 函数的覆盖不再起作用 有人有想法怎么办 覆盖示例 text Custom sortable true dataIndex customsort doSort function s
  • 在Java中删除数字中的数字[关闭]

    Closed 这个问题不符合堆栈溢出指南 目前不接受答案 如何删除整数的第一位数字 我的输入是一个整数 例如 i 123456789 然后我想删除第一位数字 使 i 等于 23456789 try this n n int Math pow
  • 如何找到mysql的默认服务器字符集?

    在 FreeBSD 8 2 上使用 MySQL 如何找到默认服务器字符集 是否有一些我可以运行的命令或我可以检查的文件 UPDATE 其实我想知道如何找到default服务器字符集and the current服务器字符集 正如下面记录的服
  • 使用方法级安全性处理 AccessDenied

    我有一个用 Spring Security 保护的方法 如下所示 PreAuthorize hasRole add user public void addUser User user 如果没有足够权限的用户尝试调用它 抛出 accessD
  • 修改引号的 auto_match,为 Sublime Text 2 添加额外的引号字符

    Sublime Text 2 非常有帮助地结束了我所有的引言 是否可以修改它使用的字符 例如 如果我想将 反引号 添加到列表中 skuroda 的回答效果很好 在 Mac OSX 上 请转至 Sublime Text 2 gt Prefer
  • Spring Boot:使用database和application.properties进行配置

    我需要将 Spring Boot 应用程序的配置保存在数据库中 是否可以将数据库信息存储在application properties并使用它们连接到数据库并从那里检索所有其他属性 So my application properties看
  • FXMLLoader如何加载FXML的控制器?

    当我在 JavaFX 中调用 FXMLLoader load 时会发生什么 假设 FXML 控制器扩展了一个具有构造函数的类 能否保证构造函数会被调用 如果不是 如何创建该对象的新实例 例如 在下面的代码中 会调用 TextField 构造
  • html5 - 获取相对坐标中的设备方向旋转

    我正在尝试改变两者之间的方向deviceorientation沿左右轴和上下轴的事件 这些轴通常定义为电话x and y axis https developer mozilla org en US docs Web Guide Event