svg动态绘制路径效果,使用snap.js库,近适用于path标签。
解决“webkitAnimationEnd入场动画切换”在安卓机兼容性问题
问题描述:
在手机端H5中,当一个图片入场动画执行完毕后,我们想让它循环执行另一个动画,就是用webkitAnimationEnd这个方法,比如代码是这样的:1
2
3
4
5
6$(document).on("webkitAnimationEnd", ".p54", function(){
$(".p54").removeClass('rollIn').addClass('pulse infinite').css({
"animation-delay" : "0s",
"-webkit-animation-delay" : "0s",
})
});
这个写法在IOS机型中没有问题,但是在安卓机上并不会执行下一个pulse这个动画。
解决方案是:
在p54这个标签外再套一层div,比如命名为p54_parent,当p54动画执行完后,让p54_parent执行下一个动画,代码是这样的:1
2
3$(document).on("webkitAnimationEnd", ".p54", function(){
$(".p54_parent").addClass('pulse infinite');
});
这样,就可以完美解决这个兼容性问题,安卓机也没有问题
无刷新上传文件的2种方法
今天在网上刷到一篇文章《三种无刷新上传文件的方法》,于是自己亲手试了试,果然可行。自己只学会了其中的两种,就把自己尝试的demo和结果记录下来:
首先是第一种:
使用FormData上传文件,formdata可以封装form标签对象,其中对象中是以键值对的形式存在的。我们可以使用append方法来添加键值,如:
1 | var oMyForm = new FormData(); |
这里我就直接来上代码介绍如何使用formData来上传图片:
1 | <!DOCTYPE html> |
注释对代码进行了介绍,就是把formData通过ajax发到后端去。
然后php代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23<?php
$firstname = $_POST['firstname'];
$filename = time() . substr($_FILES['file']['name'], strrpos($_FILES['file']['name'],'.'));
$response = array();
if(move_uploaded_file($_FILES['file']['tmp_name'], $filename)){
$response['status'] = 1; //成功
$response['filename'] = $filename;
$response['firstname'] = $firstname;
} else {
$response['status'] = -1;
}
echo json_encode($response);
?>
这样就可以后端就会保存到图片了。以上,整个上传图片的流程结束。
接下来是使用iframe来无刷新上传文件的demo
普通的按钮,点击后页面会跳转到提交的地址,而这个地址是根据form标签的target属性指定的,所以只要我们创建个iframe标签,然后指定跳转到这个iframe地址就可以获取到后端返回的数据,也不用跳转页面了,拿到数据后,再把iframe删掉就可以了,具体代码如下:
HTML代码: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<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<form action="upload1.php" method="post" enctype="multipart/form-data">
<input type="text" name="firstname">
<input type="file" id="file" name="file">
<input type="submit" id="submit" value="提交">
</form>
<script>
document.getElementById('submit').onclick = function(event){
var iframe = document.createElement("iframe");
iframe.width = 0;
iframe.height = 0;
iframe.border = 0;
iframe.name = "form-iframe";
iframe.id = "form-iframe";
iframe.setAttribute("style", "width:0;height:0;border:none");
this.form.appendChild(iframe);
this.form.target = "form-iframe";
iframe.onload = function(){
var img = document.createElement("img");
var responseData = this.contentDocument.body.textContent
|| this.contentWindow.document.body.textContent;
//获取iframe的内容,即服务返回的数据
var json = JSON.parse(responseData);//后端返回的json
console.log(json);
img.src = json.filename;
document.getElementsByTagName("form")[0].appendChild(img);//显示图片
setTimeout(function(){//删掉iframe
var _frame = document.getElementById("form-iframe");
_frame.parentNode.removeChild(_frame);
}, 100);
}
}
</script>
</body>
</html>
上面的按钮点击函数里,就是创建iframe标签,然后通过target属性指定到这个iframe,再在iframe的load函数里,或者后端返回的数据,拿到数据后,再删除iframe.
php代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23<?php
$firstname = $_POST['firstname'];
$filename = time() . substr($_FILES['file']['name'], strrpos($_FILES['file']['name'],'.'));
$response = array();
if(move_uploaded_file($_FILES['file']['tmp_name'], $filename)){
$response['status'] = 1; //成功
$response['filename'] = $filename;
$response['firstname'] = $firstname;
} else {
$response['status'] = -1;
}
echo json_encode($response);
?>
php后端代码和第一种没有什么区别,都是获取表单数据。
HTML id标签会自动生成全局变量
最近在看《你不知道的JavaScript》这本书,里面写道带有ID的HTML标签会自动生成同名的全局变量,我测试了下,上代码:1
2
3
4
5
6
7
8
9
10
11
12
13
14<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<div id="foo"></div>
<script>
console.log(foo);
foo.innerHTML = "123";
</script>
</body>
</html>
测试结果:带有ID的HTML标签会自动生成同名的全局变量。
记得去年遇到过这样的问题,当时我还很纳闷,现在看来,也就释然了。所以以后还是少用id属性吧。
构造函数和原型的异同
有两种写法:
1、1
2
3
4
5
6
7
8
9
10
11
12
13function a(age){
this.name = "sam";
this.age = age;
var that = this;
this.getAge = function(){
return that.age;
}
}
// a.prototype.getAge = function() {
// return this.age;
// };
var B = new a(200);//200
var C = new a(300);//300
2、1
2
3
4
5
6
7
8
9
10
11
12
13function a(age){
this.name = "sam";
this.age = age;
var that = this;
// this.getAge = function(){
// return that.age;
// }
}
a.prototype.getAge = function() {
return this.age;
};
var B = new a(200);//200
var C = new a(300);/300
以上两种写法虽然执行结果相同,但是原理却不同,第一种是通过构造函数生成实例,第二种是通过prototype原型。他们的不同体现在:
1、两个实例的getAge函数指向不同:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15function a(age){
this.name = "sam";
this.age = age;
var that = this;
// this.getAge = function(){
// return that.age;
// }
}
a.prototype.getAge = function() {
return this.age;
};
var B = new a(200);
var C = new a(300);
console.log(B.getAge == C.getAge); //true
console.log(C.getAge);
原型的函数指向的都是同一个函数。
构造函数指向的确是不同的:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15function a(age){
this.name = "sam";
this.age = age;
var that = this;
this.getAge = function(){
return that.age;
}
}
// a.prototype.getAge = function() {
// return this.age;
// };
var B = new a(200);
var C = new a(300);
console.log(B.getAge == C.getAge); //false
console.log(C.getAge);
2、第二点不同就是生成的实例会占用内存,大量的实例就会出现网页卡顿的情况,比如飞机大战中,每个子弹每个飞机都是实例的话,他们去做碰撞检测时会明显的卡顿,所以尽量写成原型的函数,这样逼格也更高,js代码更优雅。
/**更新**/
再看两种写法的对比:
1、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<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
function ceshi(){
var current = 1;
function a(){current++;console.log(current);}
function b(){console.log('b');}
function c(){console.log('c');}
return {
a:a,
b:b,
c:c
}
};
var CESHI = new ceshi();
var CESHI2 = new ceshi();
console.log(CESHI.a == CESHI2.a);//false
CESHI.a();//2
CESHI2.a();//2
</script>
</body>
</html>
这种就是生成实例,两个实例的指向不同,所以不相等,CESHI和CESHI2没有任何关联。
2、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<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
ceshi = function (){
var current = 1;
function a(){current++;console.log(current);}
function b(){console.log('b');}
function c(){console.log('c');}
return {
a:a,
b:b,
c:c
}
}();
ceshi.a();//2
ceshi.a();//3
console.log(ceshi.a == ceshi.a);//true
</script>
</body>
</html>
这种写法形成了闭包,可以通过ceshi这个变量访问内部变量,所以指向的a()也是相同的。
/*更新*/
封装模块写法:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22(function(globle){
var module = (function(){
var data = "sectet";
return {
bool : true,
string: "a string",
array : [1, 2, 3, 4, 5],
object : {
lang : 'en-US'
},
getData : function(){
return data;
},
setData : function(value){
return (data = value)
}
};
})();
globle.module = module;
})(this);
module.setData(3);
console.log(module.getData())
JS自定义回调函数
对于jQuery的回调函数,想搞懂他的原理,然后又想到了之前在公司的代码框架里就有自定义回调函数:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<script>
function a(callback){
console.log(1);
console.log(2);
if(callback){callback();}
}
function b(){
console.log("回调B");
}
function c(){
console.log("回调C");
}
a(b);
a(c);
</script>
</body>
</html>
简单来说,就是传参。记录之
手机端快速点击按钮播放音效的优化
今天突发奇想,想试一个在手机端点击按钮,播放音效的效果,这种效果可以用来作为射击子弹,发生碰撞时出现的音效。原理不难,就是添加audio标签,设置MP3地址,然后播放。但是细心的同学就会发现在快速点击按钮时,每一次创建audio标签,然后设置src,就会对一次对音频文件的请求,这样是很不好的,在测试了一番后,总结出了两种解决方法。
1、当点击的时候,先判断前面的audio标签是否播放完毕,上码: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<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<input type="button" value="播放" id="btn">
<script>
var btn = document.getElementById("btn");
btn.onclick = function(){
var audioArr = document.getElementsByTagName("audio");
for(var i = 0; i < audioArr.length; i++){
if(audioArr[i].ended){
audioArr[i].play();
return;
}
}
var audio = document.createElement("audio");
audio.src=audio.src || "http://chongqing.sinaimg.cn/20160913_hack/GameSpawn.mp3";
document.body.appendChild(audio);
audio.autoplay = 'autoplay';
audio.play();
// console.log(audio.ended);
// if(audioArr.length != 0){
// // audioArr[0].pause();
// audioArr[0].currentTime = 0;
// audioArr[0].play();
// }else{
// var audio = document.createElement("audio");
// audio.src = "http://chongqing.sinaimg.cn/20160913_hack/GameSpawn.mp3";
// document.body.appendChild(audio);
// audio.autoplay = 'autoplay';
// audio.play();
// }
}
</script>
</body>
</html>
这样的话,刚开始会多加载几次资源,加载的最多数就是你点击的最快数。当你点不到那么快时,这种是很好的优化方法。
2、每次点击让他重新播放,上码: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<!DOCTYPE html>
<html lang="en">
<head>
</head>
<body>
<input type="button" value="播放" id="btn">
<script>
var btn = document.getElementById("btn");
btn.onclick = function(){
var audioArr = document.getElementsByTagName("audio");
// for(var i = 0; i < audioArr.length; i++){
// if(audioArr[i].ended){
// audioArr[i].play();
// return;
// }
// }
// var audio = document.createElement("audio");
// audio.src=audio.src || "http://chongqing.sinaimg.cn/20160913_hack/GameSpawn.mp3";
// document.body.appendChild(audio);
// audio.autoplay = 'autoplay';
// audio.play();
// console.log(audio.ended);
if(audioArr.length != 0){
// audioArr[0].pause();
audioArr[0].currentTime = 0;
audioArr[0].play();
}else{
var audio = document.createElement("audio");
audio.src = "http://chongqing.sinaimg.cn/20160913_hack/GameSpawn.mp3";
document.body.appendChild(audio);
audio.autoplay = 'autoplay';
audio.play();
}
}
</script>
</body>
</html>
这种方法只会请求一次资源,但是在手机端播放效果不如第一种方法理想。
总结:所以总的来说,建议还是第一种比较好,另外看create.js对音效的处理也是按第一种方式来的。
另外在手机端要把onclick换成ontouchstart。
blob对象之上传图片本地预览
看到网上有人说blob上传图片到服务器,相对Base64来说是个更好的选择,于是自己尝试了下:1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<input id="choose" type="file" value="选择">
<img id="img" src="" alt="" height="100px">
<script>
var choose = document.getElementById("choose");
var img = document.getElementById("img");
choose.onchange = function (e){
var f = e.target.files[0];
var src = window.URL.createObjectURL(f);
img.src = src;
}
</script>
</body>
</html>
以上即可实现了选择图片本地预览。
animate.css配合JS的使用
刚刚在前端群里看到有人问animate如何配合JS使用,再给他讲解了一下后觉得应该在博客中记录下来,以能帮到更多人的更好的使用animate.css,其实这个CSS库在动效方面蛮好用的,记得我之前面试公司的考试就是做一个动效类的H5,那时候我用的是jqueryUI的库,放在手机上非常的庞大,也略卡顿,划过下一页之后再滑到上一页,就没有动效了。后来去了公司之后才知道的animate.css类库,于是自己又结合JS封装一下方法,页面之间的滑动不管滑多少次都会重新展示动画,废话不多说,上代码:
1、首先引入animate.CSS库和zepto库。
2、HTML的代码这样写:1
2
3
4
5
6<div class="page page1 animated fadeIn hide">
<img src="p11.png" class="pos_abs animated p11" data-class="bounceInDown" data-delay="0.3s">
<img src="p12.png" class="pos_abs animated p12" data-class="bounceIn" data-delay="1.3s">
<img src="p13.png" class="pos_abs animated p13" data-class="fadeInUp" data-delay="2.3s">
<img src="p14.png" class="pos_abs animated p14" data-class="fadeInUp1 infinite" data-delay="3.3s" alt="">
</div>
animated是需要有动效的元素,data-class是动画效果名称,data-delay是元素延时时间,通过延时时间的排列来达到展示动画的衔接。
3、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
102
103
104
105
106
107
108
109
110
111
112
113(function(globle){
var ff = (function(){
return{
num: 1,
divHtmlArr:[],
total : $(".page").length,
next : function(){
if(this.num < this.total){
$(".page" + this.num).addClass("fadeOut hide");
this.initHtml(this.num-1, $(".page" + this.num));
this.num++;
this.setAnimation(this.num);
}
},
setHtml : function (index,div){
if(!this.divHtmlArr[index]){
this.divHtmlArr[index] = div; //将每一屏代码存放到数组
}
},
getHtml : function (div){ //获取html代码
return $(div).html();
},
initHtml : function (index,div){ //初始化html代码
$(div).html(this.divHtmlArr[index]);
},
last : function(){
if(this.num > 1){
$(".page" + this.num).addClass("fadeOut hide");
this.initHtml(this.num-1, $(".page" + this.num));
this.num--;
this.setAnimation(this.num);
}
},
setAnimation : function(pageNum){
var html = this.getHtml($(".page" + pageNum));
this.setHtml(pageNum-1, html);
$(".page" + pageNum).removeClass("fadeOut hide");
var AnimateImg = $(".page" + pageNum).find(".animated");
$(AnimateImg).each(function(index, value){
var animationStyle = $(this).data("class");
var animationDelay = $(this).data("delay");
$(this).addClass(animationStyle).css({
"animation-delay":animationDelay,
"-webkit-animation-delay":animationDelay
});
})
},
IsPC : function() {
var userAgentInfo = navigator.userAgent;
var Agents = ["Android", "iPhone",
"SymbianOS", "Windows Phone",
"iPad", "iPod"];
var flag = true;
for (var v = 0; v < Agents.length; v++) {
if (userAgentInfo.indexOf(Agents[v]) > 0) {
flag = false;
break;
}
}
return flag;
},
autoView : function(userAgent){
var screen_w=parseInt(window.screen.width),scale=screen_w/640;
if(/Android (\d+\.\d+)/.test(userAgent)){
var version=parseFloat(RegExp.$1);
$("head").prepend(version>2.3?'<meta id="auto_view" name="viewport" content="width=640, initial-scale = '+scale+',user-scalable=1, minimum-scale = '+scale+', maximum-scale = '+scale+', target-densitydpi=device-dpi">':'<meta name="viewport" content="width=640, target-densitydpi=device-dpi">');
}else{
$("head").prepend('<meta id="auto_view" name="viewport" content="width=640, initial-scale = '+scale+' ,minimum-scale = '+scale+', maximum-scale = '+scale+', user-scalable=no, target-densitydpi=device-dpi">');
};
if(this.IsPC()){
document.body.style.margin = "0px auto";
}
},
loadImg : function(){
var totalNum = 0;
var jiazai = 0;
var imgs = document.getElementsByTagName("img");
var imgLen = imgs.length;
function setBaiNum(bai){
$("#baifen_txt").text(bai);
if(bai == 100){
setTimeout(function(){
$(".p1_close").addClass('hide');
ff.setAnimation(1);
}, 500);
}
}
for(var i = 0; i < imgLen; i++){
if(imgs[i].complete){
jiazai++;
var baifenbi = Math.floor(jiazai/imgLen*100);
setBaiNum(baifenbi);
continue;
}
imgs[i].onload = function(){
jiazai++;
var baifenbi = Math.floor(jiazai/imgLen*100);
setBaiNum(baifenbi);
}
}
},
toPage: function(num){
$(".page" + this.num).addClass('hide');
ff.setAnimation(num);
ff.num = num;
}
}
})();
globle.ff = ff;
})(this);
这是我对整个动效js的封装的一个对象,在编写好HTML后,直接复制这个代码,当前页滑到下一页可以调用ff.next(),若要通过按钮的点击来滑到某一页就调用ff.toPage(num)。setHtml()、getHtml()的方法是为了初始化HTML代码,以便滑到上一页的时候可以再次展示动效。
注意一点:绑定点击事件用$(document).on(“click”,“.class”,function(){})的方式来绑定。如果用普通的$(“.class”).click(function(){})这种方法来绑定的话,setHtml()方法会把绑定在元素上的事件也抹掉。
(完)
手机端重力感应接口及应用
现在微信开发如火如荼,各种基于微信的H5市场上也是很火爆,今天做个笔记就是跟大家分享手机端重力感应的应用,根据重力感应接口我们可以得到手机的方向,移动速度,xyz轴偏移量,现在先上所有数据展示,大家有兴趣的也可以亲身测试: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<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8"/>
<title>H5获取陀螺仪/重力感应(参考网上资源)</title>
<meta name="viewport"
content="width=device-width,initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no,target-densitydpi=device-dpi"/>
<style type="text/css">
body{font-size: 24px;}
span{color:#f00;}
a{text-decoration: none;color:#f00;}
a:hover{color:#000;}
</style>
</head>
<body>
<!--
DeviceOrientationEvent是获取方向,得到device静止时的绝对值;
DeviceMotionEvent是获取移动速度,得到device移动时相对之前某个时间的差值比
设备定位API,该API允许你收集设备的方向和移动信息。此外,该API只在具备陀螺仪功能的设备上使用。
-->
<h3>请用手机浏览器访问</h3>
<p>EGRET白鹭版降临:<br/><a href="http://weixin.shinycg.com/weixin/DeviceOrientation" target="_blank">http://weixin.shinycg.com/weixin/DeviceOrientation</a></p>
<p>左右:<span id="alpha">0</span></p>
<p>前后:<span id="beta">0</span></p>
<p>扭转:<span id="gamma">0</span></p>
<p>指北针指向:<span id="heading">0</span>度</p>
<p>指北针精度:<span id="accuracy">0</span>度</p>
<hr/>
<p>x轴加速度:<span id="x">0</span>米每二次方秒</p>
<p>y轴加速度:<span id="y">0</span>米每二次方秒</p>
<p>z轴加速度:<span id="z">0</span>米每二次方秒</p>
<hr/>
<p>x轴加速度(考虑重力加速度):<span id="xg">0</span>米每二次方秒</p>
<p>y轴加速度(考虑重力加速度):<span id="yg">0</span>米每二次方秒</p>
<p>z轴加速度(考虑重力加速度):<span id="zg">0</span>米每二次方秒</p>
<hr/>
<p>左右旋转速度:<span id="Ralpha">0</span>度每秒</p>
<p>前后旋转速度:<span id="Rbeta">0</span>度每秒</p>
<p>扭转速度:<span id="Rgamma">0</span>度每秒</p>
<hr/>
<p>上次收到通知的间隔:<span id="interval">0</span>毫秒</p>
<script type="text/javascript">
init();
function init(){
if (window && window.DeviceMotionEvent)
window.addEventListener("devicemotion", motionHandler, false);
if (window && window.DeviceOrientationEvent)
window.addEventListener("deviceorientation", orientationHandler, false);
}
function orientationHandler(event) {
document.getElementById("alpha").innerHTML = event.alpha||0;
document.getElementById("beta").innerHTML = event.beta||0;
document.getElementById("gamma").innerHTML = event.gamma||0;
document.getElementById("heading").innerHTML = event.webkitCompassHeading||0;
document.getElementById("accuracy").innerHTML = event.webkitCompassAccuracy||0;
}
function motionHandler(event) {
document.getElementById("interval").innerHTML = event.interval||0;
var acc = event.acceleration;
document.getElementById("x").innerHTML = acc.x||0;
document.getElementById("y").innerHTML = acc.y||0;
document.getElementById("z").innerHTML = acc.z||0;
var accGravity = event.accelerationIncludingGravity;
document.getElementById("xg").innerHTML = accGravity.x||0;
document.getElementById("yg").innerHTML = accGravity.y||0;
document.getElementById("zg").innerHTML = accGravity.z||0;
var rotationRate = event.rotationRate;
document.getElementById("Ralpha").innerHTML = rotationRate.alpha||0;
document.getElementById("Rbeta").innerHTML = rotationRate.beta||0;
document.getElementById("Rgamma").innerHTML = rotationRate.gamma||0;
}
</script>
</body>
</html>
以上是重力感应接口所有的参数,那么根据这些参数我们就可以做出:
1、摇动计数,根据偏移量阀值来计算摇动的次数,次数达到一定数目,就触发某种事件,摇一摇开红包就是个例子: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<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
<style>
#ceshi{
font-size: 50px;
}
</style>
</head>
<body>
<div id="ceshi"></div>
<script>
function init(){
if (window.DeviceMotionEvent) {
// 移动浏览器支持运动传感事件
window.addEventListener('devicemotion', deviceMotionHandler, false);
}
}
// 那么,我们如何计算用户是否是在摇动手机呢?可以从以下几点进行考虑:
// 1、其实用户在摇动手机的时候始终都是以一个方向为主进行摇动的;
// 2、用户在摇动手机的时候在x、y、z三个方向都会有相应的想速度的变化;
// 3、不能把用户正常的手机运动行为当做摇一摇(手机放在兜里,走路的时候也会有加速度的变化)。
// 从以上三点考虑,针对三个方向上的加速度进行计算,间隔测量他们,考察他们在固定时间段里的变化率,而且需要确定一个阀值来触发摇一摇之后的操作。
// 首先,定义一个摇动的阀值
var SHAKE_THRESHOLD = 3000;
// 定义一个变量保存上次更新的时间
var last_update = 0;
// 紧接着定义x、y、z记录三个轴的数据以及上一次触发的时间
var x;
var y;
var z;
var last_x;
var last_y;
var last_z;
// 为了增加这个例子的一点无聊趣味性,增加一个计数器
var count = 0;
function deviceMotionHandler(eventData) {
// 获取含重力的加速度
var acceleration = eventData.accelerationIncludingGravity;
// 获取当前时间
var curTime = new Date().getTime();
var diffTime = curTime -last_update;
// 固定时间段
if (diffTime > 100) {
last_update = curTime;
x = acceleration.x;
y = acceleration.y;
z = acceleration.z;
var speed = Math.abs(x + y + z - last_x - last_y - last_z) / diffTime * 10000;
if (speed > SHAKE_THRESHOLD) {
// TODO:在此处可以实现摇一摇之后所要进行的数据逻辑操作
count++;
document.getElementById("ceshi").innerHTML = count;
}
last_x = x;
last_y = y;
last_z = z;
}
}
init()
</script>
</body>
</html>
2、左右偏移角度,手机平放是0度,往左偏就是负数度,往右同理,根据这个接口我们就可以做:飞机大战,根据偏转角度来实现主角飞机在屏幕中的移动,可以参考我做的demo:http://www.sanmuweb.com/shoot/index.html(手机端才能正常试玩),效果略简陋,但是逻辑通了。
3、还有个跟重力感应相关的插件就是parallax.js,这个插件在电脑端可以通过鼠标实现图片的分层偏移,手机端可以通过重力感应实现,见demo:http://www.sanmuweb.com/zhongli3.html
OK,记录一下,欢迎交流。