如何从Javascript访问加速度计/陀螺仪数据?

151

我最近发现了一些网站似乎可以访问我的笔记本电脑上的加速度计或陀螺仪,检测方向或运动的变化。

这是如何完成的?我必须订阅 window 对象上的某种事件吗?

在哪些设备上(笔记本电脑、手机、平板电脑)已知可以使用这种方法?


NB: 实际上,我已经知道了这个问题的部分答案,并且我将立即发布它。我在这里发布问题的原因是让每个人都知道 Javascript 可以在某些设备上获取加速度计数据,并挑战社区发布关于这个主题的新发现。目前,几乎没有对这些功能的文档记录。


非常努力,非常感谢。您认为三年后答案需要更新吗? - Bartek Banachewicz
@BartekBanachewicz 感谢你指出这个问题。我将把答案转移到“社区维基”,希望有更多最新知识的人会更新它以反映当前的技术水平。 - Jørn Schou-Rode
我找不到这个操作是否需要用户同意。我不想提出一个新问题,因为它完全符合你的问题。也许我们可以在这里添加这个问题?有人知道这是否需要明确同意吗?这在所有浏览器和所有移动操作系统中都是这种情况吗? - Silver
4个回答

186

目前有三个不同的事件,可能会或可能不会在客户端设备移动时触发。其中两个与方向有关,最后一个与运动有关:

  • ondeviceorientation已知可在Chrome桌面版上使用,并且大多数苹果笔记本电脑似乎具有此功能所需的硬件。它还可以在iOS 4.2上的iPhone 4的Mobile Safari上使用。在事件处理程序函数中,您可以访问作为该函数唯一参数提供的事件数据上的alphabetagamma值。

  • onmozorientation 在 Firefox 3.6 及更高版本上受支持。同样,这在大多数苹果笔记本电脑上都可以正常工作,但也可能适用于带有加速计的 Windows 或 Linux 机器。在事件处理程序函数中,查找作为第一个参数提供的事件数据上的 xyz 字段。

  • ondevicemotion已知可在 iPhone 3GS +4 和 iPad 上使用(均使用 iOS 4.2),并提供与客户端设备当前加速度相关的数据。传递给处理程序函数的事件数据具有accelerationaccelerationIncludingGravity,每个轴都有三个字段:xyz

“地震检测”示例网站使用一系列if语句来确定要附加哪个事件(以某种优先顺序),并将接收到的数据传递给一个公共的tilt函数:

if (window.DeviceOrientationEvent) {
    window.addEventListener("deviceorientation", function () {
        tilt([event.beta, event.gamma]);
    }, true);
} else if (window.DeviceMotionEvent) {
    window.addEventListener('devicemotion', function () {
        tilt([event.acceleration.x * 2, event.acceleration.y * 2]);
    }, true);
} else {
    window.addEventListener("MozOrientation", function () {
        tilt([orientation.x * 50, orientation.y * 50]);
    }, true);
}

常数因子2和50用于将后两个事件的读数与第一个事件的读数“对齐”,但这些绝非精确表示。对于这个简单的“玩具”项目,它可以正常工作,但如果你需要将数据用于稍微严肃一点的事情,你就必须熟悉不同事件提供的值的单位并尊重它们:)


10
有时候一个回答完全准确! - Scott Evernden
1
如果有人好奇-ondevicemotion适用于Firefox 8.0,但比例错误(0-9),但在后来的版本中似乎已经修复了(10.0)。Opera Mobile上没有一个版本适用,所有标准版本在默认的Nokia N9浏览器上都能很好地工作。 - Nux
2
MozOrientation事件在Firefox 6中被标记为过时并移除。因此,现在它们都使用标准化的API。 - Chris Morgan
这在Firefox 30中似乎不起作用,如this fiddle所示。:( - bwinton
旁注:Plax.js被用于Github的404和500页面,使用ondeviceorientation - Yosh

23

不能在其他帖子的优秀解释中添加评论,但想提到一个很好的文档来源可以在这里找到。

只需像这样注册加速度计事件函数即可:

if(window.DeviceMotionEvent){
  window.addEventListener("devicemotion", motion, false);
}else{
  console.log("DeviceMotionEvent is not supported");
}

使用处理程序:

function motion(event){
  console.log("Accelerometer: "
    + event.accelerationIncludingGravity.x + ", "
    + event.accelerationIncludingGravity.y + ", "
    + event.accelerationIncludingGravity.z
  );
}

为磁力计注册以下事件处理器:

if(window.DeviceOrientationEvent){
  window.addEventListener("deviceorientation", orientation, false);
}else{
  console.log("DeviceOrientationEvent is not supported");
}

使用处理程序:

function orientation(event){
  console.log("Magnetometer: "
    + event.alpha + ", "
    + event.beta + ", "
    + event.gamma
  );
}

运动事件中还有一些针对陀螺仪的字段,但这似乎并不被所有设备都支持(例如在三星Galaxy Note上无法正常工作)。

GitHub 上有一个简单的可用代码。


如果在 iOS < 13 上禁用了传感器,window.DeviceOrientationEvent会返回undefined吗? - savram

17
在2019年及以后,使用DeviceOrientation API是实现此功能的方法。这在桌面和移动设备上大多数现代浏览器中可用。
window.addEventListener("deviceorientation", handleOrientation, true);

After registering your event listener (in this case, a JavaScript function called handleOrientation()), your listener function periodically gets called with updated orientation data.

The orientation event contains four values:

  • DeviceOrientationEvent.absolute
  • DeviceOrientationEvent.alpha
  • DeviceOrientationEvent.beta
  • DeviceOrientationEvent.gamma

The event handler function can look something like this:

function handleOrientation(event) {
  var absolute = event.absolute;
  var alpha    = event.alpha;
  var beta     = event.beta;
  var gamma    = event.gamma;
  // Do stuff with the new orientation data
}

1

这里提供一个有用的备选方案:https://developer.mozilla.org/en-US/docs/Web/Events/MozOrientation

function orientationhandler(evt){


  // For FF3.6+
  if (!evt.gamma && !evt.beta) {
    evt.gamma = -(evt.x * (180 / Math.PI));
    evt.beta = -(evt.y * (180 / Math.PI));
  }

  // use evt.gamma, evt.beta, and evt.alpha 
  // according to dev.w3.org/geo/api/spec-source-orientation


}

window.addEventListener('deviceorientation',  orientationhandler, false);
window.addEventListener('MozOrientation',     orientationhandler, false);

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接