移动端2
_______________________________________________________________________________________________
十二、手机震动
navigator.vibrate = navigator.vibrate || navigator.webkitVibrate || navigator.mozVibrate ||
navigator.msVibrate;
if(navigator.vibrate){ // 判断设备是否支持震动
var shock = document.getElementById("shock");
shock.onclick = function(){
navigator.vibrate(50); //震动1次: 震动毫秒数
navigator.vibrate([5000,3000,1000]); //震动多次: 奇位数是震动毫秒数,偶位数是震动停止毫秒数
navigator.vibrate(0); //停止震动: 传入0或空数组
};
}
注意: 对navigator.vibrate方法的调用并不会引起手机循环振动,当将参数中需要震动的时间进行完毕后,就会停止震动
_______________________________________________________________________________________________
十三、手机摇动
if(window.DeviceMotionEvent){ //判断手机是否支持摇一摇
var speed = 25;
var x = y = z = lastX = lastY = lastZ = 0;
window.addEventListener('devicemotion', function(){
var acceleration = event.accelerationIncludingGravity;
x = acceleration.x;
y = acceleration.y;
if(Math.abs(x-lastX) > speed || Math.abs(y-lastY) > speed){ //当摇动距离大于限定距离时
//摇动时发生的事件
}
lastX = x;
lastY = y;
}, false);
}
_______________________________________________________________________________________________
十四、全屏显示
var full = document.getElementById("full");
//判断是否支持切换到全屏状态
var fullscreenEnabled = document.fullscreenEnabled || document.mozFullScreenEnabled ||
document.webkitFullscreenEnabled || document.msFullscreenEnabled;
if(fullscreenEnabled){
full.onclick = function(){
var fullscreenElement = document.fullscreenElement || document.mozFullScreenElement ||
document.webkitFullscreenElement; //查找是否有处于全屏状态的节点
if(!fullscreenElement){
launchFullscreen(full);
}else{
exitFullscreen();
}
}
}
function launchFullscreen(elem){ //使某一个节点全屏显示
if(elem.requestFullscreen){
elem.requestFullscreen();
}else if(elem.mozRequestFullScreen){
elem.mozRequestFullScreen();
}else if(elem.msRequestFullscreen){
elem.msRequestFullscreen();
}else if(elem.webkitRequestFullscreen){
elem.webkitRequestFullScreen();
}
}
function exitFullscreen(){ //取消全屏
if(document.exitFullscreen){
document.exitFullscreen();
}else if(document.msExitFullscreen){
document.msExitFullscreen();
}else if(document.mozCancelFullScreen){
document.mozCancelFullScreen();
}else if(document.webkitExitFullscreen){
document.webkitExitFullscreen();
}
}
注意: 放大一个节点时:
Firefox自动将该元素放大至全屏状态,width:100%; height:100%
Chrome则是将该节点放在屏幕的中央,保持原来大小,其他部分变黑
UC浏览器会旋转屏幕
#full:-webkit-full-screen{ 全屏时应用的样式
width: 80%;
height: 80%;
}
#full:-moz-full-screen{}
#full:-ms-fullscreen{}
#full:fullscreen{}
_______________________________________________________________________________________________
visibilitychange事件: 浏览器标签页被隐藏或显示的时候会触发,隐藏时记录时间戳,显示时记录时间戳,求二者之差/1000得到离开时间(秒)
若是倒计时的话可以判断visibilityState == 'visible'里面重新获取时间戳,重启倒计时
var Visibility={ start:0, end:0, s:0 };
document.addEventListener('webkitvisibilitychange', function(){
if(document.webkitVisibilityState == 'hidden'){
Visibility.start = new Date().getTime();
}else{ //visibilityState == 'visible'
Visibility.end = new Date().getTime();
Visibility.s = ((Visibility.end-Visibility.start)/1000); //离开时间: 单位为秒
}
});
document.addEventListener('mozvisibilitychange', function(){
if(document.mozVisibilityState == 'hidden'){
Visibility.start = new Date().getTime();
}else{
Visibility.end = new Date().getTime();
Visibility.s = ((Visibility.end-Visibility.start)/1000);
}
})
_______________________________________________________________________________________________
防止遮罩层下面的内容滑动(滚动穿透):
① 弹出遮罩层后, 动态设置 body{overflow: hidden;}
②在'touchstart'事件中:e.preventDefault(); //除IE外的浏览器
e.returnValue=false; //IE系列
document.addEventListener("touchstart", function(e){ //或者使用'touchmove'也可以
if($(".mask").length>0 && $(".mask").css("display")!="none"){
e.preventDefault(); //当显示遮罩层时,禁止滑动
}
}, {passive: false});
③ 设置 body{position: fixed;} 但滚动条的位置会丢失,需要保存滚动条位置,关闭时还原滚动位置
scrollTop = (window.pageYOffset||document.documentElement.scrollTop)-(document.documentElement.clientTop||0); //打开时保存页面卷去的高度
document.body.style.position = "fixed"; //设置为固定定位
document.body.style.top = -scrollTop + 'px'; //设置top为 '-页面卷去的高度'
document.scrollingElement.scrollTop = scrollTop; //关闭时再还原页面卷去的高度
当显示遮罩层上的文字与遮罩层元素平级时:
if($(".mask_toast").css("display")!="none"){ //判断遮罩层是否已经显示
$(".mask_toast").css("margin-top",parseInt($(".mask_toast").css("margin-top"))+scrollTop);
} //设置提示文字的margin-top为原来的margin-top加上页面卷去的高
触摸遮罩层的灰色层,隐藏遮罩层
document.addEventListener("touchstart", function(e){
if($(".mask").css("display") != "none" && $(e.target).is(".mask")){
$(".mask").hide();
e.preventDefault(); //阻止后续触发 click事件、a链接
}
}, { passive: false });
注意: 从chrome56开始,在window、document和body上注册的touchstart和touchmove事件处理函数,会默认为是passive:true。浏览器忽略preventDefault()可以立即滚动,提高滚动效果
如: window.addEventListener('touchmove', fn)
window.addEventListener('touchmove', fn, { passive: true })
这两句的效果一样
如果在window、document、body的touchstart和touchmove事件处理函数中调用e.preventDefault(),会被浏览器忽略掉,并不会阻止默认行为
解决方案: 2个
① 注册处理函数时,明确声明不是被动的
window.addEventListener('touchmove', fn, {passive: false})
② 应用CSS属性 touch-action:none; 这样任何触摸事件都不会产生默认行为,但是touch事件照样触发
________________________________________________________________________________________________
移动端和PC端判断手指(鼠标)的滑动方向及距离
反弹效果: 在元素距离边界为0时,根据滑动距离修改元素的transform:translateY(Y),并在touchend时还原状态
移动端:
$(".demo").on("touchstart", function(e){
e.preventDefault();
startX = e.originalEvent.changedTouches[0].pageX, //jQuery中的API,zepto中没有
startY = e.originalEvent.changedTouches[0].pageY; //jQuery中的API
});
$(".demo").on("touchmove", function(e){
e.preventDefault();
moveEndX = e.originalEvent.changedTouches[0].pageX,
moveEndY = e.originalEvent.changedTouches[0].pageY,
X = moveEndX - startX,
Y = moveEndY - startY,
absX = Math.abs(X),
absY = Math.abs(Y);
if( absX > absY){
if( X > 0 ){
console.log("从左向右");
}else{
console.log("从右向左");
}
}else if( absX < absY){
if( Y > 0 ){
console.log("从上向下");
}else{
console.log("从下向上");
}
}else{
console.log("没有滑动");
}
});
原生写法:
var touch = { startX:0, startY:0, moveEndX:0, moveEndY:0,
X:0, Y:0, absX:0, absY:0, endX:0, endY:0 };
document.body.addEventListener("touchstart", function(e){
touch.startX = e.touches[0].pageX;
touch.startY = e.touches[0].pageY;
});
document.body.addEventListener("touchmove", function(e){
touch.moveEndX = e.touches[0].pageX;
touch.moveEndY= e.touches[0].pageY;
touch.X =touch.moveEndX -touch.startX;
touch.Y =touch.moveEndY -touch.startY;
touch.absX = Math.abs(touch.X);
touch.absY = Math.abs(touch.Y);
if(touch.absX > touch.absY){ //可设置touch.absX>300时,触发转换事件
if(touch.X > 0 ){
console.log("从左向右");
}else if(touch.X < 0){
console.log("从右向左");
}
}else if(touch.absX < touch.absY){ //可设置touch.absY>300时,触发转换事件
if(touch.Y > 0){
console.log("从上向下");
}else if(touch.Y < 0){
console.log("从下向上");
}
}else{
console.log("没有滑动");
}
});
document.body.addEventListener("touchend", function(e){
touch.endX = e.changedTouches[0].pageX;
touch.endY = e.changedTouches[0].pageY;
console.log('滑动结束:',touch.endX,touch.endY);
});
PC端:
$(".demo").mousedown(function(e){
e.preventDefault();
startX = e.pageX;
startY = e.pageY;
$(this).mousemove(function(e){
e.preventDefault();
moveEndX = e.pageX;
moveEndY = e.pageY;
X = moveEndX - startX;
Y = moveEndY - startY;
absX = Math.abs(X),
absY = Math.abs(Y);
if( absX > absY){
if( X > 0 ){
console.log("从左向右");
}else{
console.log("从右向左");
}
}else if( absX < absY){
if( Y > 0 ){
console.log("从上向下");
}else{
console.log("从下向上");
}
}else{
console.log("没有滑动");
}
})
}).mouseup(function(){
$(this).off("mousemove")
})
下拉刷新
.container{
position: relative;
}
.scroll{
width: 100%;
margin-top: 0;
position: absolute;
top: 0;
left: 0;
height: 500px;
background-color: #DDD;
}
<div class="container">
下拉刷新
var scroll = document.querySelector('.scroll');
var container = document.querySelector('.container');
var touchStart = 0;
container.addEventListener('touchstart', function(event){
touchStart = event.targetTouches[0].pageY;
}, {passive: false});
container.addEventListener('touchmove', function(event){
var touch = event.targetTouches[0];
console.log(touch.pageY - touchStart);
scroll.style.top = scroll.offsetTop + touch.pageY - touchStart + 'px';
touchStart = touch.pageY;
}, {passive: false});
container.addEventListener('touchend', function(){
touchStart = 0;
var top = scroll.offsetTop;
if(top > 70){
console.log('下拉刷新');
}
if(top > 0){
scroll.style.transition = 'all 0.3s ease-in-out';
scroll.style.top = '0px';
setTimeout(function(){
scroll.style.transition = 'none';
}, 300)
}
}, {passive: false});
_______________________________________________________________________________________________
微信浏览器如果按系统的返回按钮,页面会被缓存,但是js文件没有重新调用(各项数值不会修改),可调用pageshow事件来解决
e.addeventListener('pageshow', function(e){
e.persisted && fn(); //fn:返回页面后需要运行的函数
})
_______________________________________________________________________________________________
复制内容
document.execCommand()方法: 可以允许运行命令来操作可编辑区域的内容
bool = document.execCommand(aCommandName, aShowDefaultUI, aValueArgument)
方法返回一个Boolean值,表示操作是否成功
① aCommandName: 表示命令名称,比如:copy、cut、print等
② aShowDefaultUI: 是否展示用户界面,一般是false
③ aValueArgument: 有些命令需要额外的参数,一般用不到
<input type="text" id="copyInput" value="想要复制的内容"readonly/> //只读,防止拉起键盘
function copy(){
var input = document.querySelector('#copyInput');
input.select();
input.setSelectionRange(0, 9999); //input.select()在ios下没有选中全部内容
//用 input.setSelectionRange(0, input.value.length)解决
var boolean =document.execCommand('copy');
console.log(boolean)
}
https://clipboardjs.com/ //参考插件
复制的内容进行换行:
① 把input换成textarea,input无法输入换行,可换成多行文本textarea
② 将换行符 <br> 使用 \r\n 代替
_______________________________________________________________________________________________
window.location.href = "weixin://" //从网页打开微信客户端
从网页跳转到微信内的某个页面:
if(/baiduboxapp/i.test(navigator.userAgent)){
window.location.replace("bdbox://utils?action=sendIntent&minver=7.4¶ms=%7B%22intent%22%3A%22weixin://dl/business/?ticket=???%23Intent%3Bend%22%7D");
}else{
window.location.replace("weixin://dl/business/?ticket=???");
}
weixin:// 是微信客户端注册的scheme url,用来在浏览器里唤起微信客户端
dl/business 是一种消息类型实际上就是跳到了: weixin://dl/business/?ticket=(微信URL Schemes)#wechat_redirect
ticket: 该值是由微信后端产生32位的HASH值(时间戳+URL随机生成),属于URL临时票据信息,在微信服务器上会与真实URL的进行绑定,所以微信可以通过这个值能跳到真实地址,该值有时效性,并非一直不变,要不断请求接口获取该值才能正常访问(需要与微信合作,才能获取此ticket)
在京东做活动时,会有漏洞,可以通过京东跳转到指定页面,某些平台会出售此漏洞
_______________________________________________________________________________________________
键盘访问网站的常用操作:
①Tab键索引控件元素
可按次序不断:focus控件元素,包括链接(带href属性)、按钮、输入框等表单元素或设置了tabindex的普通元素(也可以设置tabindex为某个数字,修改Tab显示的顺序)
②Enter键触发当前元素处于 :focus 状态的点击行为
按下Enter键,相当于鼠标点击了这个元素,从而触发相应效果
<input type="checkbox" id="che"/> 可使用空格键修改状态
③ 上下键上下滚动网页
④ Space空格键滚动一屏网页(当前没有:focus checkbox时)
⑤ Home键返回顶部
⑥ End键滚动到底部
注意:
① 对于<form>表单元素,若里面有type="submit"类型的按钮,则浏览器天然支持单行输入框的回车提交行为(当前:focus链接时),否则,若没有<form>元素,也没有原生的提交按钮,则Enter不会触发任何默认行为
例: <input id="btn" type="submit"> <label class="btn" for="btn">提交</label>
用<label>替代提交按钮,实现Enter提交表单行为,并修改提交按钮的样式
或者使用a标签代替submit,使用ajax提交
<form>
...
<a href="javascript:void(0)" class="login">登录</a>
<input type="submit" style="display: none"/>
</form>
$('.login, input[type=submit]').click(function(e){
e.preventDefault(); //阻止默认提交
...
});
_______________________________________________________________________________________________
阻止Safari浏览器自带的弹簧滚动特效
方法①
window.addEventListener('touchmove', function(e){ //阻止外层window的tocuch事件
e.preventDefault();
}, {passive: false});
document.querySelector('body').addEventListener('touchmove', function(e){ //只允许部分touch
e.stopPropagation();
}, false)
方法②
body{ overscroll-behavior:none; } //允许控制浏览器的滑动溢出行为,当到达滚动区域的边界时会发生的行为
________________________________________________________________________________________________
ios中,定位在底部的输入框获得焦点时,输入框被覆盖,无法显示
原因: input获得焦点后,fixed失效
方案一、
Web API接口: 使用scrollIntoView,将input输入框显示在可视区域
inputOnFocus(e){ //输入框获得焦点时,元素移动到可视区域
setTimeout(function(){ //延时: 键盘弹起需要时间
e.target.scrollIntoView(true); //true: 元素的顶端将和其所在滚动区的可视区域的顶端对齐
//false: 底端对齐
}, 200)
}
方案二、不使用fixed将元素固定在底部
<div class="main">
<section></section>
<footer> <input type="text" /> </footer>
</div>
.main{ position:relative; height:100% }
section{ box-sizing:border-box; height:100%; padding-bottom:4rem;
overflow-y:scroll; -webkit-overflow-scrolling:touch //此属性可使滚动流畅 }
footer{ position:absolute; height:4rem; overflow:hidden; left:0; right:0; bottom:0 }
解决input输入框在ios中无法输入,光标不出现:
-webkit-user-select: text;
user-select: text;
在聚焦到输入框时,使当前元素出现到指定位置,避免光标错位:
e.target.scrollIntoView(true)
e.target.scrollIntoViewIfNeeded()