JS 使用 DeviceAcceleration.x 无缝平移图像

JS use DeviceAcceleration.x to pan image seamlessly

我有一个比视口大的图像,我正试图根据设备加速值在 x 平面上进行平移。

            _____________________
            |                   |
            |   Device          |
            |                   |
    ________|___________________|__________
    |       |                   |         |
    |       |   Image           |         |
    |       |                   |         |
    |_______|___________________|_________|
            |                   |
            |                   |
            |                   |
            |                   |
            |___________________|


            <-------------------->
                    X axis      

我可以获得半不错的结果,但没有什么比这更好的了。

根据我的理解,我需要:

到目前为止我有类似的东西:(我正在使用 gyronorm.js 所以加速度数据被称为 data.dm.x

var accelX = data.dm.x
var currTrans = $('#pano').css('-webkit-transform').split(/[()]/)[1]
var posX = parseInt(currTrans.split(',')[4])
var newPos = posX+accelX
$('#pano').css({'-webkitfr-transform':'translateX('+(newPos)+'px)'})

我觉得我在这里遗漏了一个核心概念,但经过数小时的研究后我找不到它。

你说对了核心概念。但是您的应用程序可能缺少使重新定位看起来流畅的动画(您不希望您的图像立即跳转 50 像素)。您可以使用 CSS 动画创建从旧坐标到新坐标的流畅过渡。

这里有一个简单的例子,如何在重新定位时为变换设置动画(包括猫)- https://codepen.io/dmonad/pen/aGbbrv

  1. 使用 css transitions 为变换设置动画。
  2. 使用 transition timing 微调您的过渡。

目前您的转换也如下所示:

        _____________________
        |                   |
        |   Device          |
        |                   |
        |___________________|__________
        ||                  |         |
        ||  Image           |         |
        ||                  |         |
        ||__________________|_________|
        |                   |
        |                   |
        |                   |
        |                   |
        |___________________|


        <-------------------->
                X axis      

因此请确保将图像置于中心位置(您也可以设置负 translateX(-500px) 值)。这是计算图像位置初始值的方法:

var img = document.querySelector('img')
// width of the image
var imgWidth = img.getBoundingClientRect().width
// width of the container that holds the image
var containerWidth = document.body.clientWidth

var initialPosition = -imgWidth/2 + containerWidth/2
img.style.setProperty('transform', 'translateX(' + initialPosition + 'px)')

你的代码的主要问题是你通过加速度改变图像的位置,但加速度是速度随时间的变化,所以:

// speed and positionX are declared somewhere else
speed += accelX
positionX += speed

...会更好。

您认为频率相关是正确的,因为您需要执行以下操作:

// speed and positionX are declared somewhere else
speed += accelX / frequency
positionX += speed / frequency * some_number

...如果你要改变频率,为了让一切都成比例。 (some_number是一个数字,用于缩放位置,使其以想要的速度移动)

不幸的是,仅使用加速度计数据找到设备的相对位置非常困难,因为误差会随着时间的推移而累积。如果您有理论上的 "perfect accelerometer",上面的示例代码会起作用,但我怀疑任何人都有其中之一的 phone,因此上面的代码实际上并没有解决您的问题(请参阅 calculating distances using accelerometer).

我建议使用倾斜(设备方向)而不是加速度:

var translate = 0;
var pano = $('#pano');
var frequency = 40;
var multiplier = 5;
var gn;

function init_gn() {
    var args = {
      logger: null,
      gravityNormalized: true,
      frequency: frequency
    };
    gn = new GyroNorm();
    gn.init(args).then(start_gn).catch(console.log);
}

function start_gn() {
    gn.start(gnCallBack);
}

function gnCallBack(data) {
    var tilt = data.do.gamma; // device orientation
    translate += tilt / frequency * multiplier;
    pano.css('transform', 'translateX(' + translate + 'px)');
}

此代码可让您将 phone 倾斜到一侧以平移图像。