1、像素知识
px: css pixels,逻辑像素,浏览器使用的抽象单位
dp,pt:device independent pixels ,设备无关像素
dpr:devicePixelRatio 设备像素缩放比
计算公司:1px=(dpr)*dpr*dp
2、Viewport
手机浏览器默认为我们做了两件事。
一:页面渲染在一个980px(iso)的Viewport。
二:缩放
是有 visual Viewport 与 layout viewport.
最佳meta设置如下:
<meta name="viewport" content="width=device-width,initial-scale=1,user-scalable=no">
window.innerWidth/document.body.clientWidth=缩放比
【布局Viewport】=【设备宽度】=【度量Viewport】
3、Tap基础事件
自定义Tap事件原理:
在touchstart、touchend时记录时间、手指位置,在touchend时进行比较,如果手指位置为同一位置(或允许移动一个非常小的位移值),
且事件间隔较短(一般认为是200ms),且过程中未触发过touchmove,即可认为触发了手持设备的"click",一般称为"tap"。
Tap透传Bug
解决方案:
1、使用缓动动画,过渡300ms延迟。
2、中间层dom元素的加入,让中间层接受这个“穿透”事件,稍后隐藏。
3、上下都使用"tap"事件。
四、Touch 基础事件
touchstart、touchmove、touchend、touchcancel(系统取消touch时触发)。
Bug:
Android只会触发一次touchstart,一次touchmove,touchend不触发。
在 touchmove中加入:event.preventDefault(),但会导致默认行为不发生,比如scroll。
触摸板上下左右滑动事例:
<style> .touchpad{ width: 100%; height: 200px; font-size: 40px; text-align: center; line-height: 200px; background: rgba(0,0,0,0.5); position: relative; color: #ddd; } .ball{ display: none; position: absolute; width: 25px; height: 25px; border-radius: 15px; background-color: #7AE6FF; top: 0; left: 0; } p{ height: 30px; } </style> </head> <body> <p id="desc"></p> <div id="touchPad" class="touchpad">触摸板</div> <div id="ball" class="ball"></div> <script src="../js/zepto.js"></script> <script type="text/javascript"> var touchpad = document.querySelector('#touchPad'), ball = document.querySelector('#ball'), desc = document.querySelector('#desc'); //获取touch的点(兼容mouse事件) var getTouchPos = function(e){ var touches = e.touches; if(touches && touches[0]) { return { x : touches[0].clientX , y : touches[0].clientY }; } return { x : e.clientX , y: e.clientY }; } //计算两点之间距离 var getDist = function(p1 , p2){ if(!p1 || !p2) return 0; return Math.sqrt((p1.x - p2.x) * (p1.x - p2.x) + (p1.y - p2.y) * (p1.y - p2.y)); } //计算两点之间所成角度 var getAngle = function(p1 , p2){ var r = Math.atan2(p2.y - p1.y, p2.x - p1.x); var a = r * 180 / Math.PI; return a; }; //获取swipe的方向 var getSwipeDirection = function(p2,p1){ var dx = p2.x - p1.x; var dy = -p2.y + p1.y; var angle = Math.atan2(dy , dx) * 180 / Math.PI; if(angle < 45 && angle > -45) return "right"; if(angle >= 45 && angle < 135) return "top"; if(angle >= 135 || angle < -135) return "left"; if(angle >= -135 && angle <= -45) return "bottom"; } var startEvtHandler = function(e){ var pos = getTouchPos(e); ball.style.left = pos.x + 'px'; ball.style.top = pos.y + 'px'; ball.style.display = 'block'; var touches = e.touches; if( !touches || touches.length == 1 ){ //touches为空,代表鼠标点击 point_start = getTouchPos(e); time_start = Date.now(); } } var moveEvtHandler = function(e){ var pos = getTouchPos(e); ball.style.left = pos.x + 'px'; ball.style.top = pos.y + 'px'; point_end = getTouchPos(e); e.preventDefault(); } //touchend的touches和targetTouches没有对象,只有changeTouches才有 var endEvtHandler = function(e){ ball.style.display = 'none'; var time_end = Date.now(); //距离和时间都符合 if(getDist(point_start,point_end) > SWIPE_DISTANCE && time_start- time_end < SWIPE_TIME){ var dir = getSwipeDirection(point_end,point_start); touchPad.innerHTML = 'swipe'+dir; } } var SWIPE_DISTANCE = 30; //移动30px之后才认为swipe事件 var SWIPE_TIME = 500; //swipe最大经历时间 var point_start, point_end, time_start, time_end; //判断是PC或者移动设备 var startEvt, moveEvt, endEvt; if("ontouchstart" in window){ startEvt="touchstart"; moveEvt="touchmove"; endEvt="touchend"; }else{ startEvt="mousedown"; moveEvt="mousemove"; endEvt="mouseup"; } touchpad.addEventListener(startEvt, startEvtHandler); touchpad.addEventListener(moveEvt, moveEvtHandler); touchpad.addEventListener(endEvt, endEvtHandler); </script> </body>