Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

JS use DeviceAcceleration.x to pan image seamlessly

I have an image larger than viewport that I'm trying to pan on the x plan according to device Acceleration value.

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


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

I can get to semi-decent results but nothing like great.

From my understanding I need to :

  • get the acceleration value
  • get the object position
  • combine these two value (maybe with frequency ?)
  • Apply the new position to the object

So far I have something like : (I'm using gyronorm.js so the acceleration data is called 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)'})

I feel like I'm missing a core concept here but after hours of research I wasn't able to find it.

like image 363
kursus Avatar asked Apr 13 '18 14:04

kursus


1 Answers

The major problem with your code is that you are changing the position of the image by the acceleration, but acceleration is the change in speed over time, so:

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

...would be better.

You are correct that the frequency is relevant, since you would need to do something like:

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

... in order to get make everything scale if you were to change the frequency. (some_number is a number used to scale the position so that it moves at the speed to want)

Unfortunately finding the relative position of a device using only accelerometer data is very difficult since error accumulates over time. The example code above would work if you had a theoretical "perfect accelerometer", but I doubt anyone has a phone with one of those, so the above code doesn't actually solve your problem (see calculating distances using accelerometer).

I would suggest using the tilt (device orientation) rather than acceleration:

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)');
}

This code lets you tilt your phone to the side to pan on the image.

like image 182
Oli Avatar answered Oct 12 '22 14:10

Oli