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
- 使用 css transitions 为变换设置动画。
- 使用 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 倾斜到一侧以平移图像。
我有一个比视口大的图像,我正试图根据设备加速值在 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
- 使用 css transitions 为变换设置动画。
- 使用 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 倾斜到一侧以平移图像。