移动端开发技巧(三)——移动端300ms延迟 & 自己实
2019-07-07 本文已影响44人
临安linan
完整的移动端开发笔记请戳https://github.com/zenglinan/Mobile-note
目录:为了解决方案1(viewport适配)的缺点(无法对部分缩放,部分不缩放),出现了vw适配
流程
- 将设计稿(假设750px)上需要适配的尺寸转换成vw,比如页面元素字体标注的大小是32px,换成vw为 32/(750/100) vw
- 对于需要等比缩放的元素,CSS使用转换后的单位
- 对于不需要缩放的元素,比如边框阴影,使用固定单位px
(1) viewport设置 <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
把layout viewport 宽度设置为设备宽度,不需要缩放
(2) 用js定义css的自定义属性--width,表示每vw对应的像素数。
(3) 根据设计稿标注设置样式,比如标注稿里元素宽度为20px。这里设置 calc(20vw / var(--width))
// HTML
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>viewport缩放实战</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, minimum-scale=1">
<script>
const WIDTH = 750
document.documentElement.style.setProperty('--width', (WIDTH/100));
</script>
</head>
// CSS
header {
font-size: calc(28vw / var(--width));
}
优点
可以对需要缩放的元素进行缩放,保留不需缩放的元素
缺点
书写复杂,需要用calc计算
- 移动端click事件300ms延迟与解决方案
- 自己实现fastclick
1. 移动端click事件300ms延迟与解决方案
前置知识
移动端点击监听执行顺序touchstart > touchmove > touchend > click
出现原因
iPhone是全触屏手机的鼻祖,当时的网页都是为了大屏幕设备设置的(移动端没有设置<meta name=""viewport>),
为了方便用户阅读,设定为用户快速双击时,缩放页面。
当用户点击第一下时,设备会等待300ms,若这300ms内没有再次点击,才响应click事件。
解决方案
- 设置
<meta name="viewport" content="width=device-width">
解决之后,click事件仍会有些许延迟,那是因为click事件执行顺序在touchend之后,正常延迟。 - 不使用click事件,改用touchstart事件
- 使用fastclick库
2. 自己实现fastclick
fastclick是一个库,用来解决移动端click事件300ms延迟。
使用
document.addEventListener('DOMContentLoaded', function() {
FastClick.attach(document.body)
}, false)
原理
移动端在点击第一下的时候会等待300ms,看用户是否点击第二下。
fastclick的原理就是监听touchend事件,取消原本300ms后真正的click事件,自己生成分发一个点击事件。
简单实现
const FastClick = !function(){
const attach = (dom) => {
let targetElement = null
dom.addEventListener('touchstart',function(e){
targetElement = e.target // 获取点击对象
})
dom.addEventListener('touchend',function(e){
e.preventDefault() // 阻止默认click事件
let touch = e.changeTouches[0] // 获取点击的位置坐标
let clickEvent = document.createEvent('MouseEvents')
// 初始化自定义事件
clickEvent.initMouseEvent('click', true, true, window, 1, touch.screenX, touch.screenY, touch.clientX, touch.clientY, false, false, false, false, 0, null)
targetElement.dispatchEvent(clickEvent) // 自定义事件的触发
})
}
return {attach}
}()