移动端基于陀螺仪实现重力感应效果

要想实现重力感应效果,必须取到设备的方向值。
有两种Javascript事件负责处理设备方向信息。

第一种是DeviceOrientationEvent,它会在传感器检测到设备在方向上产生变化时触发。
第二种是DeviceMotionEvent,它会在加速度发生改变时触发。
陀螺仪功能主要用到第一种,即DeviceOrientationEvent。

用法如下:

1
window.addEventListener("deviceorientation", handleOrientation, false);

事件对象中包含4个值:

1
2
3
4
5
6
function handleOrientation(event) {
var absolute = event.absolute;
var alpha = event.alpha;
var beta = event.beta;
var gamma = event.gamma;
}

absolute表示是否跟地球坐标系一致。

alpha表示沿Z轴上的旋转角度,范围 [0, 360]alpha为0时表示设备的顶部正指北极方向,当设备向左旋转时,alpha将增加。
alpha

beta表示沿X轴上的旋转角度,也就是前后旋转角度,范围 [-180, 180]。当beta为0° 时表示设备顶部和底部与地表面的距离是一样的,当设备向前翻转时,beta递增到180°,向后翻转递减到-180°。
beta

gamma表示沿Y轴上的旋转角度,也就是左右倾斜时的角度,范围 [-90, 90]gamma等于0°表示设备左右两边与地表面的距离相等,当设备向右翻转时,gamma递增到90° ,向左翻转时,递减到-90°。
gamma

一般的应用场景,我们利用beta和gamma去做就可以了,比如全景图等。

先来一个二维的例子(根据设备的移动来缓动背景图,给人一种高大上的感觉)。
关键js代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
if (window.DeviceOrientationEvent) {
window.addEventListener('deviceorientation', handleOrientation, false);
function handleOrientation(event) {
var x = event.beta; // 范围是[-180, 180]
var y = event.gamma; // 范围是[-90, 90]
// 这里我们把x的数值控制在-90到90,因为我们不需要让设备翻转倒过来。
if (x > 90) {x = 90};
if (x < -90) {x = -90};
// 设置偏移最大值
var max = 100;
document.body.style = 'transform: translate3d('+max*x/90+'px, '+max*y/90+'px, 0px)'
}
} else {
document.write('your browser is not support');
}

扫码体验:
背景缓动例子

再来一个css3d的例子。
关键代码如下:
html

1
2
3
4
5
6
7
8
9
10
<div class="container">
<div id="cube" style="-webkit-transform: translateZ( -200px) rotateX( 40deg) rotateY( 40deg);">
<figure class="front">1</figure>
<figure class="back">2</figure>
<figure class="right">3</figure>
<figure class="left">4</figure>
<figure class="top">5</figure>
<figure class="bottom">6</figure>
</div>
</div>

css

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
.container {
width: 400px;
height: 400px;
position: relative;
margin: 400px auto 0;
/*border: 1px solid #CCC;*/
-webkit-perspective: 1200px;
-moz-perspective: 1200px;
-o-perspective: 1200px;
perspective: 1200px;
}
#cube {
width: 100%;
height: 100%;
position: absolute;
-webkit-transform-style: preserve-3d;
-moz-transform-style: preserve-3d;
-o-transform-style: preserve-3d;
transform-style: preserve-3d;
-webkit-transform: translateZ( -200px);
-moz-transform: translateZ( -200px);
-o-transform: translateZ( -200px);
transform: translateZ( -200px);
}
#cube figure {
display: block;
position: absolute;
width: 396px;
height: 396px;
border: 2px solid black;
line-height: 396px;
font-size: 240px;
font-weight: bold;
color: white;
text-align: center;
}
#cube .front {
background: hsla( 0, 100%, 50%, 0.7);
}
#cube .back {
background: hsla( 60, 100%, 50%, 0.7);
}
#cube .right {
background: hsla( 120, 100%, 50%, 0.7);
}
#cube .left {
background: hsla( 180, 100%, 50%, 0.7);
}
#cube .top {
background: hsla( 240, 100%, 50%, 0.7);
}
#cube .bottom {
background: hsla( 300, 100%, 50%, 0.7);
}
#cube .front {
-webkit-transform: translateZ( 200px);
-moz-transform: translateZ( 200px);
-o-transform: translateZ( 200px);
transform: translateZ( 200px);
}
#cube .back {
-webkit-transform: rotateY(180deg) translateZ( 200px);
-moz-transform: rotateY(180deg) translateZ( 200px);
-o-transform: rotateY(180deg) translateZ( 200px);
transform: rotateY(180deg) translateZ( 200px);
}
#cube .right {
-webkit-transform: rotateY( 90deg) translateZ( 200px);
-moz-transform: rotateY( 90deg) translateZ( 200px);
-o-transform: rotateY( 90deg) translateZ( 200px);
transform: rotateY( 90deg) translateZ( 200px);
}
#cube .left {
-webkit-transform: rotateY( -90deg) translateZ( 200px);
-moz-transform: rotateY( -90deg) translateZ( 200px);
-o-transform: rotateY( -90deg) translateZ( 200px);
transform: rotateY( -90deg) translateZ( 200px);
}
#cube .top {
-webkit-transform: rotateX( 90deg) translateZ( 200px);
-moz-transform: rotateX( 90deg) translateZ( 200px);
-o-transform: rotateX( 90deg) translateZ( 200px);
transform: rotateX( 90deg) translateZ( 200px);
}
#cube .bottom {
-webkit-transform: rotateX( -90deg) translateZ( 200px);
-moz-transform: rotateX( -90deg) translateZ( 200px);
-o-transform: rotateX( -90deg) translateZ( 200px);
transform: rotateX( -90deg) translateZ( 200px);
}

js

1
2
3
4
5
6
7
8
9
10
11
12
if (window.DeviceOrientationEvent) {
window.addEventListener('deviceorientation', handleOrientation, false);
function handleOrientation(event) {
var x = event.beta; // 范围是[-180, 180]
var y = event.gamma; // 范围是[-90, 90]
var z = event.alpha; // 范围是[0, 360]
document.getElementById('cube').style.cssText = 'transform: rotateX('+x+'deg) rotateY('+y+'deg) rotateZ('+z+'deg)';
}
} else {
document.write('your browser is not support');
}

扫码体验:
立方体

参考
https://desandro.github.io/3dtransforms/docs/introduction.html
https://developer.mozilla.org/zh-CN/docs/Web/API/Detecting_device_orientation

分享到