设备方向传感器到 CSS 转换 [英] Device orientation sensor to CSS transform

查看:28
本文介绍了设备方向传感器到 CSS 转换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我创建了

<小时>

我的代码侦听设备的方向事件并尝试将值转换为适合 css 变换比例,如下所示:

let phone = document.querySelector(".phone");window.addEventListener('deviceorientation', (event) => {phone.style.transform ="rotateY(" + (event.alpha) + "deg) "+"rotateX(" + (90 - event.beta) + "deg) "+"rotateZ(" + (event.gamma ) + "deg)";})

但是,如果我玩弄这些值足够多,我的小部件和 chrome 小部件就会不同步.显然,我的计算是错误的,我错过了什么?

要测试我的代码,只需转到演示,打开开发工具传感器选项卡并尝试小部件.

任何帮助将不胜感激.

更新:进入传感器选项卡:打开开发工具,按 Esc,在第二个面板上点击左侧的 3 点并选择传感器.

更新:有问题的值的示例是:
阿尔法:-77.6163
测试版:-173.4458
伽玛:-40.4889

解决方案

在 Chrome 和 chrome 中就是这样做的:

codepen

重要的部分是当我们应用gamma角度变换时,轴已经通过之前的beta角度变换旋转.所以我们需要将伽马旋转角度应用到考虑β角的变换轴而不是(0, 0, 1)轴.

来源:

function degreeToRadians (deg) {返回 deg * Math.PI/180;}类欧拉角{构造函数(阿尔法,贝塔,伽马){this.alpha = alpha;this.beta = 测试版;this.gamma = 伽玛;}toRotate3DString() {const gammaAxisY = -Math.sin(degreesToRadians(this.beta));const gammaAxisZ = Math.cos(degreesToRadians(this.beta));常量轴 = {阿尔法:[0, 1, 0],测试版:[-1, 0, 0],伽马:[0,伽马轴Y,伽马轴Z]};返回 ("rotate3d(" +axis.alpha.join(",") +"," +this.alpha +"度)" +"rotate3d(" +axis.beta.join(",") +"," +这个.beta +"度)" +"rotate3d(" +axis.gamma.join(",") +"," +this.gamma +度)");}}功能就绪(fn){如果 (文档.附加事件?document.readyState === "完成": document.readyState !== "加载"){fn();} 别的 {document.addEventListener("DOMContentLoaded", fn);}}准备好(() => {let phone = document.querySelector(".phone");window.addEventListener("deviceorientation", event => {控制台日志(事件);const eulerAngles = new EulerAngles(event.alpha, -90 + event.beta, event.gamma)phone.style.transform = eulerAngles.toRotate3DString();});});

I've created the following widget (see demo here) to mimic the sensors tab on the chrome developer tab:



My code listens to the orientation event of the device and tries to convert the values to fit the css transform scale, like so:

let phone = document.querySelector(".phone");
    window.addEventListener('deviceorientation', (event) => {
      phone.style.transform =
        "rotateY(" + ( event.alpha) + "deg) "
        +
        "rotateX(" + (90 - event.beta) + "deg) "
        +
        "rotateZ(" + (event.gamma ) + "deg)";
    })

However, if I play around enough with the values, my widget and the chrome widget get out of sync. Obviously, my calculations are wrong, what am I missing?

To test my code, just go to the demo open the dev tools sensors tab and play around with the widget.

Any help would be appreciated.

Update: to get to the sensors tab: Open dev tools, press Esc, on the second panel click the 3dots on the left and choose sensors.

Update: Example of problematic values are:
alpha: -77.6163
beta:-173.4458
gamma:-40.4889

解决方案

That is how it is done in chromium and chrome:

codepen

Essential part there is that when we apply gamma angle transformation, the axis is already rotated by previous beta angle transformation. So we need to apply gamma rotation angle not to (0, 0, 1) axis but to transformed axis which considers beta angle.

Source:

function degreesToRadians (deg) {
    return deg * Math.PI / 180;
}

class EulerAngles {
  constructor(alpha, beta, gamma) {
    this.alpha = alpha;
    this.beta = beta;
    this.gamma = gamma;
  }
  
  toRotate3DString() {
    const gammaAxisY = -Math.sin(degreesToRadians(this.beta));
    const gammaAxisZ = Math.cos(degreesToRadians(this.beta));
    const axis = {
      alpha: [0, 1, 0],
      beta: [-1, 0, 0],
      gamma: [0, gammaAxisY, gammaAxisZ]
    };
    return (
      "rotate3d(" +
      axis.alpha.join(",") +
      "," +
      this.alpha +
      "deg) " +
      "rotate3d(" +
      axis.beta.join(",") +
      "," +
      this.beta +
      "deg) " +
      "rotate3d(" +
      axis.gamma.join(",") +
      "," +
      this.gamma +
      "deg)"
    );
  }
}

function ready(fn) {
  if (
    document.attachEvent
      ? document.readyState === "complete"
      : document.readyState !== "loading"
  ) {
    fn();
  } else {
    document.addEventListener("DOMContentLoaded", fn);
  }
}

ready(() => {
  let phone = document.querySelector(".phone");
  window.addEventListener("deviceorientation", event => {
    console.log(event);
    const eulerAngles = new EulerAngles(event.alpha, -90 + event.beta, event.gamma)
    phone.style.transform = eulerAngles.toRotate3DString();
  });
});

这篇关于设备方向传感器到 CSS 转换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆