目录
1 移动web第一天
2 移动web第二天
触屏事件 3 移动web第六天
- 理解
- 知道屏幕常见参数
- 了解失真的原因以及解决办法
- 了解视口、布局视口、理想视口的概念
- 应用
- 手机京东--静态页面制作
视口就是指我们在浏览器中看到的网页内容的区域
描述:
在移动端中,视口有两个,一个是布局视口另外一个是理想视口
- 布局视口,只需要了解写代码的时候不会使用
- 理想视口,需要学习了解,只要写移动web,一定要使用理想视口
- 两者的区别,只看有没有这一行代码
<meta name="viewport" content="width=device-width, initial-scale=1.0">
- 没有,那就是布局视口
- 有,就是理想视口
代码:没有添加<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>布局视口</title>
</head>
<body>
</body>
</html>
可以看到,在布局视口下,html标签的宽度变成了980px,而不是和屏幕等宽
- 980px 是手机厂商为了做兼容而设置的,因为以前的网站的版心宽度一般都是小于980px
- 把一个980px宽的页面放入到375px的小屏幕上,后果就是页面元素被缩小了(布局视口)
以上结果,不是我们在移动端希望看到的,所以我们使用理想视口而不是布局视口
只要在代码里面加入以下代码,就可以把布局视口变成了理想视口
<meta name="viewport" content="width=device-width, initial-scale=1.0">
完整代码
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>理想视口</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
div{
width: 100px;
height: 100px;
background-color: aqua;
}
</style>
</head>
<body>
<div></div>
</body>
</html>
标准的理想视口的代码的写法如下:
<meta name="viewport" content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no">
在html页面中按入meta:vp
+tab 即可快速敲入理想视口的代码 此为普通的理想视口的写法
<meta name="viewport" content="width=device-width, initial-scale=1.0">
相比普通的写法,标准的写法多了一些设置
- 后期会演示(触屏事件中的clientX/Y和pageX/Y的演示)
- 使用普通的写法可能会出现一些莫名其妙的问题
在写项目中建议使用标准的写法
参数的描述,了解即可
- meta标签用来描述或设置一个HTML网页文档的属性
- content 要设置或者描述的内容
- width 设置视口的宽度 device-width等于屏幕的宽度
- initial-scale 页面打开的时候视口放大的倍数 值:1
- user-scalable 是否允许用户缩放页面 值:no
- maximum-scale 如果允许放大的话 最大放大多少倍 值 :1
- minimum-scale 如果允许放大的话 最小放大多少倍 值 :1
- 理解京东头部的透明效果
- 手机京东倒计时效果、
- 真机调试的过程
- 3个触屏事件
- 3个触摸点数组
- 3对坐标信息
- 应用
- 封装移动端点击tap
- 封装移动端滑动swipe
- 鼠标事件不能满足多指触控的需求
- click点击事件在移动端存在延迟
演示代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>延迟.html</title>
<style>
div:nth-child(1) {
width: 200px;
height: 200px;
background-color: aqua;
margin: 100px auto;
}
</style>
</head>
<body>
<div></div>
<script>
var div = document.querySelector("div");
div.addEventListener("click", function () {
alert("点我点我");
})
</script>
</body>
</html>
在pc端下双击和在移动端下双击,div现象
解释:
在移动端上执行双击时
- 在第一次单击过后,浏览器等待了一小段时间
- 如果在短时间内
- 有第二次的点击发生,触发双击放大
- 没有第二次点击,触发的click点击事件
也就是说,在第一次点击过后,不管有没有第二次的点击产生,都会先等待一小段时间。
谁做的处理?
这个机制,也是手机厂商为了方便用户放大页面做的处理。所带来的后果就是click有延迟,降低了用户体验。
学习触屏事件的目的:
因此,我们学习触屏事件就是为了解决click延迟,封装常见的手势事件。
手指触摸到移动设备的时候所发生的一些事件
- touchstart 手指触碰到屏幕的时候触发,对比 mousedown
- touchmove 手指在屏幕上滑动的时候触发,对比mousemove
- touchend 手指离开屏幕的时候触发,对比mouseup
注意:
- 建议 dom.addEventListener 的方式绑定,不建议使用 dom.ontouchstart 的方式绑定(低版本不识别)
div.addEventListener("touchstart", function () {
})
- 触屏事件只能在移动端上,在pc端上无法触发
当多个手指触摸到屏幕上时,这些手指的坐标等相关信息,存放在三个不同的触摸点数组当中。
- touches屏幕上所有的触摸点的集合
- targetTouches目标元素上触摸点的集合
- changedTouches在目标元素上发生进入,离开和移动的触摸点的集合
给一个div绑定touchstart事件,事件中打印出这两个数组的长度
<style>
div:nth-child(1) {
width: 200px;
height: 200px;
background-color: aqua;
margin: 100px auto;
}
</style>
</head>
<body>
<div></div>
<script>
var div = document.querySelector("div");
div.addEventListener("touchstart",function (e) {
console.log("屏幕上:"+e.touches.length);
console.log("目标元素上:"+e.targetTouches.length);
})
</script>
</body>
给div绑定touchend事件,事件中分别打印targetTouches长度
<style>
div:nth-child(1) {
width: 200px;
height: 200px;
background-color: aqua;
margin: 100px auto;
}
</style>
</head>
<body>
<div></div>
<script>
var div = document.querySelector("div");
div.addEventListener("touchend",function (e) {
console.log("目标元素上:"+e.targetTouches.length);
console.log("屏幕上状态改变:"+e.changedTouches.length);
})
</script>
</body>
- 如果要获取离开屏幕的手指的信息,只能通过 touchend 事件中的 changedTouches 数组**(切记)**
- 由于 changedTouches 数组功能还不够完善,同时离开2个、3个手指时,它的长度都是1
- 当需要获取多个同时离开屏幕的手指信息时,可以同时结合3个触摸点数组来完成(了解-具体情况具体分析)
- clientX/clientY 相对于浏览器视口的坐标
- pageX/pageY 相对于页面的坐标
- screenX/screenY 相对于屏幕的坐标
使用三个触屏事件touchstart,touchmove,touchend封装自己的手势事件
- 判断按下的手指个数不超过1个
- 判断手指按下的时间不能太长 300ms
- 判断手指按下的时候,滑动的距离不能太长 (自定义<5px)
-
touchstart,touchend
-
touchstart
touches.length
记录按下的时间 startTime
记录开始的坐标
-
touchend
changedTouches
如果要获取离开屏幕的手指的信息,只能通过 touchend 事件中的 changedTouches 数组**(切记)**
记录松开的时间 endTime-startTime=
记录松开手的坐标,结束的坐标-开始的坐标 =
<script>
var div = document.querySelector("div");
//开始按下的时间
var startTime;
//开始按下的坐标
var startX, startY;
//按下
div.addEventListener("touchstart", function (e) {
// 1、判断手指的个数
if (e.touches.length > 1) {
return;
}
//2、记录按下的时间
startTime = Date.now();
//3、获取开始的坐标
startX = e.touches[0].clientX;
startY = e.touches[0].clientY;
});
//离开
div.addEventListener("touchend", function (e) {
//1、判断手指的个数(记住--这里判断的是changedTouches)
if (e.changedTouches.length > 1) {
return;
}
//2
endTime = Date.now();
//判断按下时长
if (endTime - startTime > 300) {
return;
}
//3、获取松开手的坐标
var endX = e.changedTouches[0].clientX;
var endY = e.changedTouches[0].clientY;
//判断滑动的距离 5px
if (Math.abs(endX - startX) > 5 || Math.abs(endY - startY) > 5) {
return;
}
//通过验证,此时可以触发tap的点击的逻辑
console.log("自己的tap");
});
</script>
-
判断手指的个数,不能超过1个
-
判断按下的事件,不能太长(自定义800ms)
-
判断按下的距离,不能太短,大于(自定义5px)
判断距离
判断方向
<script>
var div = document.querySelector("div");
//按下的时间
var startTime;
//按下的坐标
var startX,startY;
//按下
div.addEventListener("touchstart",function (e) {
//1 判断手指的个数
if (e.touches.length > 1) {
return;
}
//2、记录按下的时间
startTime = Date.now();
//3、记录按下的坐标
startX = e.touches[0].clientX;
startY = e.touches[0].clientY;
});
//离开
div.addEventListener("touchend",function (e) {
//1、判断手指的个数
if (e.changedTouches.length > 1) {
return;
}
//2、记录时间
var endTime = Date.now();
//
if (endTime - startTime > 800) {
return;
}
//4、记录离开的坐标
var endX = e.changedTouches[0].clientX;
var endY = e.changedTouches[0].clientY;
//滑动的方向
var direction;
//先判断距离
if (Math.abs(endX - startX)>5) {
//在水平方向上发生了移动
direction = endX>startX?"right":"left";
} else if (Math.abs(endY-startY)>5) {
//在垂直方向上发生移动
direction = endY>startY?"down":"up";
} else {
//没有发生移动
return;
}
//触发滑动的逻辑
console.log(direction);
});
</script>
- 理解
- 手机京东--轮播图原生js实现
- zepto使用
- zepto定制
- 手机京东-zepto改造
- swiper.js插件使用
- 手机京东-swiper.js轮播图使用
- 应用
- 京东分类页面--静态页面
被称为移动端的jquery
1.引入js文件
2.像jquery一样进行使用
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no"> <title>03-zepto.html</title> <style> div{ width: 200px; height: 200px; background-color: aqua; margin: 100px auto; } </style> </head>
<body>
<div></div>
<!-- 引入zepto.js -->
<script src="./zepto.js"></script>
<script>
// 绑定点击事件
$("div").click(function () {
// 链式编程 显示又隐藏
$("div").hide().show();
});
</script>
</body>
</html>
不同于jquery将所有的代码都放入一个js文件中,zepto按照不同的模块拆分成了不同的js文件
当你在使用zepto的时候,出现了如以下报错的代码,那是提示你记得引入对应的模块
xxx Is not a function
如果我们需要引入zepto的很多模块的话,都单独引入反而变得麻烦
所以,最好是把一些常用模块打包到一个单独的zepto.js文件中
其实github也有定制 的介绍
-
下载nodejs 下载地址
-
安装nodejs 安装说明
-
github下载zepto项目
-
在zepto文件中,打开命令行工具 (shift+鼠标右键)
-
找到根目录的
dist
文件夹,所生成的zepto.js就是我们自己定制的zepto
- 理解
- iscroll.js插件
- 响应式布局概念
- 媒体查询
- css框架 bootstrap
- 应用
- 京东分类页面-js实现滚动条
- 京东分页页面-iscroll.js实现滚动
- bootstrap组件查文档使用
使用一套代码,可以在不同的设备(主要指屏幕的宽度)之间显示,并且提供友好的用户体验。
如:三星中国这个网站,屏幕宽度不同的时候,会自动切换样式以适应不同的设备
PC端
移动端
响应式布局核心的原理是使用了css3中的媒体查询
是一种css语法,可以根据设备的不同(主要是屏幕的宽度不同),去加载对应的css代码
我们只需要理它的作用,而代码是不用去记的。拿来修改即可使用。
以下代码分别在宽度400px,600px,800px的屏幕下显示的是不同颜色!
- 在css中写入媒体查询的代码
@media screen and (width:xxx)
除了xxx之外,其他都是关键字 - 只有当屏幕的宽度满足width:值条件时,才会去加载里面的css代码
<style>
/* 800px body->red */
@media screen and (width:800px) {
body {
background-color: red;
}
}
/* 600px body->blue */
@media screen and (width:600px) {
body {
background-color: #0094FF;
}
}
</style>
媒体类型可以理解为不同的设备i,如打印机,计算机的屏幕等。可以加载不同的媒体类型,一般时screen使用得最多
- all 匹配所有的媒体类型,默认值
- screen 匹配计算机显示器
- print 匹配打印机设备
/* 匹配所有的媒体类型 */
@media all {
body {
background-color: red;
}
}
/* 匹配屏幕 */
@media screen {
body {
background-color: red;
}
}
/* 匹配打印机 */
@media print {
body {
background-color: red;
}
}
可以根据屏幕的宽度,高度等参数进行查询。这些参数就叫做媒体特性。
- width-宽度
- min-width 最少宽度
- max-width 最大宽度
- height 高度
- min-height 最少高度
- max-height 最大高度
- aspect-ratio 视口的宽高比
- min-aspect-ratio 最少宽高比
- max-aspect-ratio 最大宽高比
<style>
/* >=800px body=>#0094FF */
@media screen and (min-width:800px) {
body {
background-color: #0094FF;
}
}
/* <800px body=>pink */
@media screen and (max-width:800px) {
body {
background-color: pink;
}
}
</style>
- not 取反
- only 实现更好的兼容
- and 连接
- or 或者
/* 取反 屏幕宽度不为800px的时候 被选中 */
@media not screen and (width:800px){
body{
background-color: red;
}
}
/* only 更好的兼容 屏幕为800px的时候被选中 */
@media only screen and (width:800px){
body{
background-color: red;
}
}
/* or 代码中体现为 逗号(,) 意思屏幕为800px或者600px的时候被选中 */
@media screen and (width:800px),screen and (width:600px) {
body{
background-color: green;
}
}
- style标签里或者css文件中
- style标签上
- link标签上
<!-- 在style标签里或者在css文件里写媒体查询 -->
<style>
@media screen and (width:800px) {
body {
background-color: red;
}
}
</style>
<!-- 在style标签上通过属性的方式写媒体查询 -->
<style media="screen and (width:800px)">
body {
background-color: red;
}
</style>
<!-- 在link标签写媒体查询 -->
<link rel="stylesheet" media="screen and (width:800px)" href="./base.css">
Bootstrap是最受欢迎的HTML、CSS和JS框架,用于开发响应式布局、移动设备优先的WEB项目
务必用最新的设计和开发标准武装你的页面。这意味着使用 HTML5 doctype 声明、添加一个
viewport
标签让页面正确支持响应式布局。将这些整合在一起后,你的页面应当像下面这样:
<!doctype html>
<html lang="en">
<head>
<!-- Required meta tags -->
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<!-- Bootstrap CSS -->
<link rel="stylesheet" href="https://cdn.bootcss.com/bootstrap/4.0.0/css/bootstrap.min.css" integrity="sha384-Gn5384xqQ1aoWXA+058RXPxPg6fy4IWvTNh0E263XmFcJlSAwiGgFAW/dAiS6JXm" crossorigin="anonymous">
<title>Hello, world!</title>
</head>
<body>
<h1>Hello, world!</h1>
<!-- Optional JavaScript -->
<!-- jQuery first, then Popper.js, then Bootstrap JS -->
<script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.slim.min.js" integrity="sha384-KJ3o2DKtIkvYIK3UENzmM7KCkRr/rE9/Qpg6aAZGJwFDMVNA/GpGFF93hXpG5KkN" crossorigin="anonymous"></script>
<script src="https://cdn.bootcss.com/popper.js/1.12.9/umd/popper.min.js" integrity="sha384-ApNbgh9B+Y1QKtv3Rn7W3mgPxhU9K/ScQsAP7hUibX39j7fakFPskvXusvfa0b4Q" crossorigin="anonymous"></script>
<script src="https://cdn.bootcss.com/bootstrap/4.0.0/js/bootstrap.min.js" integrity="sha384-JZR6Spejh4U02d8jOt6vLEHfe/JQGiRRSQQxSfFWpi1MquVdAyjUar5+76PVCmYl" crossorigin="anonymous"></script>
</body>
</html>
栅格系统按照移动规则把div的纵向排列改为类似表格的排列形式。
- 极小屏幕 xs 小于等于768px 手机设备
- 小屏幕 sm 768px ~992px 平板电脑
- 中等(普通)屏幕 md 992px~1200px - 老旧的电脑显示器
- 大屏 lg 大于1200px 大的电脑显示器
- 版心容器 .container或者 .container-fluid
- 行 .row
- 栅格代码 col-(屏幕种类)-份数 如 col-xs-11
<!-- 1 写大容器 .container-fluid -->
<div class="container-fluid">
<!-- 2 写行 .row -->
<div class="row">
<h1>col-xs-1 一列占一份 一共 12份</h1>
<!-- 3 写栅格 -->
<div class="col-xs-1">.col-xs-1</div>
<div class="col-xs-1">.col-xs-1</div>
<div class="col-xs-1">.col-xs-1</div>
<div class="col-xs-1">.col-xs-1</div>
<div class="col-xs-1">.col-xs-1</div>
<div class="col-xs-1">.col-xs-1</div>
<div class="col-xs-1">.col-xs-1</div>
<div class="col-xs-1">.col-xs-1</div>
<div class="col-xs-1">.col-xs-1</div>
<div class="col-xs-1">.col-xs-1</div>
<div class="col-xs-1">.col-xs-1</div>
<div class="col-xs-1">.col-xs-1</div>
</div>
</div>
<!-- jQuery (Bootstrap 的所有 JavaScript 插件都依赖 jQuery,所以必须放在前边) -->
<script src="https://cdn.bootcss.com/jquery/1.12.4/jquery.min.js"></script>
<!-- 加载 Bootstrap 的所有 JavaScript 插件。你也可以根据需要只加载单个插件。 -->
<script src="https://cdn.bootcss.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
补充:
- 容器提供了一种中心和水平填充站点内容的方法。使用
.container
了应答像素宽度或.container-fluid
用于width: 100%
在所有视窗和器件尺寸。
-
理解
- rem单位
- rem+媒体查询实现页面屏幕适配
- 点透
- fastclick.js
- 其他css框架
-
应用
- 优惠券案例
rem是一个相对长度单位,先学习什么是绝对长度单位和相对长度单位
绝对长度单位的大小是固定的
- px像素
相对长度单位的大小是会相对于某一个值而改变的
- %百分比一般都是相对于父元素
- em相对于自身的font-size
- rem相对于根元素html标签的fontsize
<style>
@media screen and (min-width:300px) {
html {
font-size: 100px;
}
}
@media screen and (max-width:300px) {
html {
font-size: 50px;
}
}
.px {
font-size: 0.48rem;
}
</style>
让根元素的字体与屏幕宽度产生关系,即随屏幕宽度变化而变化
onload = function () {
init()
function init () {
setHTML()
}
// 根据屏幕的宽度动态设置html标签的fontsize
function setHTML () {
// 设计稿的宽度 / 基础值 = 要适配的屏幕的宽度 / fz
// fz = 要适配的屏幕的宽度*基础值/设计稿的宽度
// 基础值
var baseVal = 100
// 设计稿的宽度
var pageWidth = 750
// 当前屏幕的宽度
var screenWidth = document.querySelector('html').offsetWidth
// 要设置的fontsize
var fz = screenWidth * baseVal / pageWidth
// 赋值给HTML标签
document.querySelector('html').style.fontSize = fz + 'px'
}
window.onresize = function () {
setHTML()
}
}
目前主流的适配移动端的解决方案是使用rem+媒体查询实现
- 在不同的媒体查询中设置不同的html标签的fontsize
- 屏幕宽度一改变,浏览器自动会加载对应的媒体查询中的html标签的fontsize
- 继而页面使用rem单位的标签,也会自动跟着改变
- 我们需要处理好,不同屏幕的html标签的fontsize的比例关系即可
<style>
/*屏幕大于或等于300px的时候加载*/
@media screen and (min-width:300px) {
html {
font-size: 100px;
}
}
/*屏幕小于300px的时候加载*/
@media screen and (max-width:300px) {
html {
font-size: 50px;
}
}
/*div中的单位都使用rem
目的是宽度和字体可以随屏幕的改变而改变
*/
.px {
width: 2.4rem;
font-size: 0.48rem;
}
</style>
- 使用媒体查询+rem还原设计稿(如设计稿为640px,用rem替换px先设计出640px大小的页面)
- 根据要适配的屏幕,添加对应的媒体查询,改变html标签的font-size
-
基础值:和设计稿等宽的媒体查询中的html的fontszie大小
-
基础值为什么要写100px(谷歌浏览器默认字体最小为12px),为方便计算
-
公式设计稿宽度/要适配的屏幕的宽度=基础值/fontsize
fz = 基础值*要适配的屏幕宽度/设计稿的宽度
-
媒体查询代码可以通过js来代替(一般还是建议,使用媒体查询)原则,可以用css实现的,尽量不用js实现
-
在PC端滚动条占宽度,移动端滚动条不占宽度,建议在移动端上测试
目前大部分浏览器已经不存在点透问题,但是还是有部分浏览器有。所以为了演示该问题,我们在火狐上进行模拟。
- a,b两个div,兄弟关系,a绝对定位在b上方
- 给a绑定tap点击事件,事件中隐藏自身
- 给b绑定click点击事件,事件中弹出对话框
模拟点击:
只点击一次a便签,发现
a隐藏,200ms过后,b标签的点击事件也被触发了
<script>
$(".A").tap(function () {
$(this).hide();
})
$(".B").click(function () {
console.log("点透发生了");
})
</script>
- 由于click点击事件在移动端上存在延迟
- 当点击完A元素后,A元素隐藏
- 200ms再触发click点击,但是由于A已经被隐藏了,就触发B元素的click点击事件
其实,在2015年底,chrome和safari浏览器通过理想视口的代码,已经把200ms的延迟给优化了,但是,可能还是存在一些第三方或者旧版的浏览器存在这个问题,为了演示需要,我们在火狐上演示!
- 所有元素都使用click点击事件(忍受click在某些浏览器上的延迟)
- 所有元素都使用tap点击事件(如果B元素是a超链接标签,则失效,因为a标签点击默认可以发生跳转)
- 使用第三方库fastclick.js
通过组合处理mousedown,mouseup,click等事件解决click点击事件在移动端上的延迟。
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0,maximum-scale=1,minimum-scale=1,user-scalable=no">
<title></title>
<!-- 引入fastclick.js -->
<script src="./fastclick.js"></script>
</head>
if ('addEventListener' in document) {
document.addEventListener('DOMContentLoaded', function () {
FastClick.attach(document.body);
}, false);
}
document.querySelector("div").onclick=function(){}