目标及目录
触屏事件
触屏事件概述
移动端浏览器兼容性较好,所以我们不需要考虑以前JS的兼容性问题,可以放心的使用原生JS书写效果,但是移动端也有自己独特的地方,比如触屏事件touch(也称触摸事件),Android和IOS都有。
touch对象代表一个触摸点。触摸点可能是手指,也可能是触摸笔。触屏事件可响应用户手指(或触控笔)对屏幕或者触控板操作。
触摸事件对象(TouchEvent)
TouchEvent 是一类描述手指在触摸平面(触摸屏、触摸板等)的状态变化的事件。这类事件用于描述一个或多个触点,使开发者可以检测触点的移动,触点的增加和减少等等。
touchstart、touchmove、touchend三个事件都有各自的事件对象。
触摸事件对象重点看三个常见对象列表:
<script>
// 1.获取元素
// 2. 手指触摸DOM元素事件
var div = document.querySelector('div');
div.addEventListener('touchstart', function (e) {
// console.log(e);// 有很多属性,目前先了解三个 touches targetTouches changedTouches
// touches 正在触摸屏幕的所有手指的列表 touches.length表示有几个触摸点
// targetTouches 正在触摸当前DOM元素的手指列表
// 如果侦听的是一个DOM元素,他们两个是一样的
// changedTouches 手指状态发生了改变的列表 从无到有或者从有到无
console.log(e.targetTouches[0]);
});
// 4. 手指离开DOM元素事件
div.addEventListener('touchend', function (e) {
// console.log(e);
// 当我们手指离开屏幕的时候,就没有了touches和targetTouches列表,但会有changedTouches
});
// 因为我们一般都是触摸元素,所以经常使用的是targetTouches
// console.log(e.targetTouches[0]); 可以得到正在触摸dom元素的第一个手指的相关信息,比如手指坐标
</script>
移动端拖动元素
- touchstart、touchmove、touchend可以实现拖动元素
- 拖动元素需要当前手指的坐标值,可以使用targetTouches[0]里面的pageX和pageY
- 移动端拖动的原理:手指移动中,计算出手指移动的距离。用盒子原来的位置+手指移动距离
- 手指移动的距离:手指滑动中的位置减去手指刚开始触摸的位置
- 手指移动的距离=盒子原来的位置+手指滑动中的位置-手指刚开始触摸的位置
拖动元素三部曲: - 触摸元素touchstart:获取手指初始坐标,同时获得盒子原来的位置
- 移动手指touchmove:计算手指的滑动距离,并且移动盒子
- 离开手指touchend
注意:手指移动也会触发滚动屏幕所以这里要阻止默认的屏幕滚动e.preventDefault();
<div></div>
<script>
// 拖动元素三部曲
// (1)触摸手指 touchstart :获取手指初始坐标,同时获得盒子原来的位置
// (2)移动手指 touchmove :计算手指的滑动距离,并且移动盒子
// (3)离开手指touchend
var div = document.querySelector('div');
var startX = 0; // 获取手指初始坐标
var startY = 0;
var x = 0; // 获取盒子的初始坐标
var y = 0;
var moveX = 0; // 手指移动的距离
var moveY = 0;
div.addEventListener('touchstart', function (e) {
// console.log(e.targetTouches[0].pageX, e.targetTouches[0].pageY);
// console.log(div.offsetWidth, div.offsetHeight);
startX = e.targetTouches[0].pageX;
startY = e.targetTouches[0].pageY;
x = div.offsetLeft;
y = div.offsetTop;
});
div.addEventListener('touchmove', function (e) {
// console.log(e.targetTouches[0].pageX, e.targetTouches[0].pageY);
moveX = e.targetTouches[0].pageX - startX;
moveY = e.targetTouches[0].pageY - startY;
div.style.left = moveX + x + 'px';
div.style.top = moveY + y + 'px';
e.preventDefault(); // 阻止屏幕滚动的默认行为
});
</script>
移动端常见特效
一案例:
在HTML中:
修改焦点图模块增加焦点图模块和小圆点模块
<!-- 焦点图模块 -->
<div class="focus">
<ul>
<li><img src="upload/focus1.jpg" alt=""></li>
<li><img src="upload/focus2.jpg" alt=""></li>
<li><img src="upload/focus3.jpg" alt=""></li>
</ul>
<!-- 小圆点 -->
<ol>
<li class="current"></li>
<li></li>
<li></li>
</ol>
</div>
在CSS中:
/* 小圆点居于右下角 */
.focus ol{
position: absolute;
bottom: 5px;
right: 5px;
}
/* 设置每个未选中的小圆点的宽高背景圆角 */
.focus ol li {
display: inline-block;
width: 5px;
height: 5px;
background-color: red;
border-radius: 2px;
list-style: none;
}
/* 更改当前选中小圆点的宽度 */
.focus ol li.current {
width: 15px;
}
修改CSS:
根据pc端轮播图书写经验需要拿第一张图放在最后面
又因为移动端的特性,有左右拖拉的效果,所以在第一张图片前加最后一张图片
.focus ul {
/* 清除浮动 */
overflow: hidden;
width: 500%;
/* 因为加了图片在第一张前面,导致默认显示那张图片,所以移动100%的距离(父亲的宽度的100%也就是ul的)这样就显示真正的第一张图片 */
margin-left: -100%;
}
.focus ul li {
float: left;
/* 将宽度缩小为父级宽度的1/5 */
width: 20%;
}
案例分析1:
- 自动播放功能
- 开启定时器
- 移动端移动,可以使用translate移动
- 图片做优雅的移动,添加过渡效果
HTML和CSS书写完毕,现在开始书写js:
window.addEventListener('load', function () {
// alert(1);
// 1.获取元素
var focus = document.querySelector('.focus');
var ul = focus.children[0];
// 获得focus的宽度
var w = focus.offsetWidth;
// 2.利用定时器自动轮播图片.
var index = 0;
var timer = setInterval(function () {
index++;
var translatex = -index * w;
ul.style.transform = 'translateX(' + translatex + 'px)';
ul.style.transition = 'all .3s';
}, 2000)
})
案例分析2:
- 自动播放功能-无缝滚动
- 注意,我们判断条件是要等到图片滚动完毕再去判断,也就是过渡完成以后判断
- 此时需要添加检测过渡完成事件 transitionend
- 判断条件:如果索引号等于3则说明走到最后一张图片,此时索引号要复原为0
// 等着我们过渡完成之后,再去判断监听过渡完成的事件 transitionend
ul.addEventListener('transitionend', function () {
if (index == 3) {
index = 0;
// console.log(index);
}
})
- 此时图片,去掉过渡效果,然后移动(生硬的移动过去)
在上述代码中添加:
// 去掉过渡效果 这样让我们的ul快速的跳到目标位置
ul.style.transition = 'none';
// 利用最新的索引号乘以宽度去滚动图片
var translatex = -index * w;
ul.style.transform = 'translateX(' + translatex + 'px)';
- 如果索引号小于0,说明是倒着走,索引号等于
- 此时图片,去掉过渡效果,然后移动
else if (index < 0) {
index = 2;
ul.style.transition = 'none';
// 利用最新的索引号乘以宽度去滚动图片
var translatex = -index * w;
ul.style.transform = 'translateX(' + translatex + 'px)';
}
控制小圆点:
- 旧方法:通过控制自定义属性index来确定给哪个li一个current属性,清除其他的current类(操作类名)
- 新方法:使用classList属性
classList
classList属性是HTML5新增的一个属性,返回元素的类名。但是ie10以上版本支持。该属性用于在元素总添加、移除及切换CSS类。有以下方法
添加类:
element.classList.add('类名');
focus.classList.add('current');
移除类
element.classList.remove('类名');
切换类
element.classList.toggle('类名);
<div class="one two"></div>
<button>开关灯</button>
<script>
// classList 返回元素的类名
var div = document.querySelector('div');
// console.log(div.classList[0]);
// 1.添加类名 是在后面追加类名,不会覆盖以前的类名,不同于className
div.classList.add('three');
//2. 移除类名
div.classList.remove('one');
// 3. 切换类
var btn = document.querySelector('button');
btn.addEventListener('click', function () {
document.body.classList.toggle('bg');
})
</script>
案例分析3:
- 小圆点跟随变化效果
- 把ol里面li带有current类名的选出来去掉类名remove
- 让当前索引号的小li加上current
- 但是,是等着过渡结束之后变化,所以这个写到transitionend事件里面
// 4.小圆点跟随变化效果
// 把ol里面li带有current类名的选出来去掉类名remove
ol.querySelector('.current').classList.remove('current');
// 让当前索引号的小li加入current (add方法)
ol.children[index].classList.add('current');
案例分析4:
- 手指滑动轮播图
- 本质就是ul跟随手指移动,简单说就是移动端拖动元素
- 触摸元素touchstart:获取手指初始坐标
- 移动手指touchmove:计算手指的滑动距离,并且移动盒子
// 5.手指滑动轮播图
var startX = 0; // 获取手指初始坐标
// 后面我们会使用这个移动距离所以要定义一个全局变量
var moveX = 0; // 手指移动的距离
ul.addEventListener('touchstart', function (e) {
startX = e.targetTouches[0].pageX;
// 手指触摸的时候就停止计时器
clearInterval(timer);
});
ul.addEventListener('touchmove', function (e) {
// 计算移动距离:
moveX = e.targetTouches[0].pageX - startX;
// 移动盒子: 盒子原来的位置+手指移动的距离
var translatex = -index * w;
// 手指拖动的时候,不需要动画效果所以要取消过渡效果
ul.style.transition = 'none';
ul.style.transform = 'translateX(' + translatex + moveX + 'px)';
});
案例分析5:
- 离开手指touchend:根据滑动的距离分不同的情况
- 如果移动距离小于某个像素,就回弹到原来的位置
- 如果移动距离大于某个像素,就上一张下一张的滑动
ul.addEventListener('touchend', function () {
//(1)如果移动距离大于50px我们就播放上一张
if (Math.abs(moveX) > 50) {
// 右滑就是播放上一张,moveX是正值
if (moveX > 0) {
index--;
}
// 左滑就是播放下一张,moveX是负值
else {
index++;
}
var translatex = -index * w;
ul.style.transform = 'translateX(' + translatex + 'px)';
ul.style.transition = 'all .3s';
}
else {
// (2)如果移动距离小于50px我们就回弹
var translatex = -index * w;
ul.style.transform = 'translateX(' + translatex + 'px)';
ul.style.transition = 'all .3s';
}
// 手指离开的时候就重新开启定时器
clearInterval(timer);
timer = setInterval(function () {
index++;
var translatex = -index * w;
ul.style.transform = 'translateX(' + translatex + 'px)';
ul.style.transition = 'all .3s';
}, 2000);
})
如果只是点击而未移动则不需要判断回弹的位置
需写入一个全局变量flag
还要写入一个e.preventDefault();//阻止屏幕默认行为
又一案例:
案例分析:
- 滚动到某个地方显示
- 事件:scroll页面滚动事件
- 如果被卷去的头部(window.pageYOffset)大于某个值就出现
- 点击后,window.scroll(0,0)然后返回顶部
// 返回顶部模块制作
var goBack = document.querySelector('.goBack');
window.addEventListener('scroll', function () {
if (window.pageYOffset >= focus.offsetHeight) {
goBack.style.display = 'block';
} else {
goBack.style.display = 'none';
}
});
goBack.addEventListener('click', function () {
window.scroll(0, 0);
})
click 延时解决方法
移动端click事件会有300ms 的延时,原因是移动端屏幕双击会缩放(double tap to zoom)页面。
解决方案:
1.禁用缩放。浏览器禁用默认的双金缩放行为并且去掉300ms的点击延迟。
<meta name="viewport" content="user-scalable=no">
2.利用touch事件自己封装这个事件解决300ms延迟
原理:
- 当我们手指触摸屏幕,记录当前触摸时间
- 当我们手指离开屏幕,用离开的时间减去触摸的时间
- 如果时间小于150ms,并且没有滑动过屏幕,那么我们就定义为点击
移动端常用开发插件
第一种方案的缺陷:有些页面就是要求能够缩放
因此研究出第三种方案:
使用插件:fastclick插件解决300ms延迟。
什么是插件
移动端要求的是快速开发,所以我们经常会借助于一些插件来帮我们完成操作,那什么是插件呢?
JS插件就是一些js文件,它遵循一定规范编写,方便程序展示效果,拥有特定功能且方便调用。如轮播图插件和瀑布流插件。
特点:一般是为了解决某个问题而专门存在,其功能单一,并且比较小。
我们以前写的animate.js 也算一个最简单的插件
fastclick插件解决 300ms延迟。使用延时
GitHub官网地址:https://github.com/ftlabs/fastclick
引入:
<script type='application/javascript' src='/path/to/fastclick.js'></script>
使用:
if ('addEventListener' in document) {
document.addEventListener('DOMContentLoaded', function() {
FastClick.attach(document.body);
}, false);
}
<style>
div {
width: 50px;
height: 50px;
background-color: pink;
}
</style>
<script src="fastclick.js"></script>
<div></div>
<script>
if ('addEventListener' in document) {
document.addEventListener('DOMContentLoaded', function () {
FastClick.attach(document.body);
}, false);
}
var div = document.querySelector('div');
div.addEventListener('click', function () {
alert(11);
})
</script>
Swiper插件的使用
中文官网地址:https://www.swiper.com.cn/
- 引入插件相关文件
- 按照规定语法使用
引入:解压文件后,将package中的js文件里的swiper.js和css文件夹里的swiper.css放入项目里
示例使用:
打开demos文件夹,以“030-pagination”为例
首先复制html
然后复制CSS:
将CSS复制进入index.css中
js中:
在主页中直接复制后,粘贴到index.js中:
window.addEventListener('load', function () {
var swiper = new Swiper('.swiper-container', {
pagination: {
el: '.swiper-pagination',
},
});
})
引入方法:
https://www.swiper.com.cn/usage/index.html
使用方法:
https://www.swiper.com.cn/api/index.html
其他移动端常见插件
- superslide: http://www.superslide2.com/
- iscroll: https://github.com/cubiq/iscroll
插件使用总结
- 确认插件实现的功能
- 去官网插看使用说明
- 下载插件
- 打开demo实例文件,查看需要引入的相关文件,并且引入
- 复制demo实例文件中的结构html,样式css以及js代码
移动端视频插件 zy.media.js
引入css,html和js,就可实现在不同的端口不同的浏览器中播放效果相同
移动端常用开发框架
框架概述
框架,顾名思义就是一套架构,它会基于自身的特点向用户提供了一套较为完整的解决方案。框架的控制权在框架本身,使用者要按照框架所规定的某种规范进行开发。
插件一般是为了解决某个问题而专门存在的,其功能单一,并且比较小。
前端常用的框架有Vue、Angular、React等。既能开发PC端,也能开发移动端
前端常用的移动端插件有swiper、superslide、iscroll等。
总结一句话:框架——是大而全的,一整套解决方案;插件——是小而转移的,为某个功能设计的解决方案
旋转木马做轮播图
bootstrap是依赖jQuery的,因此引入bootstrap之前要先引入jQuery
在https://v3.bootcss.com/javascript/#carousel中找到
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
<script src="bootstrap/js/jquery.min.js"></script>
<script src="bootstrap/js/bootstrap.min.js"></script>
<style>
.focus {
width: 800px;
height: 300px;
background-color: pink;
margin: 100px auto;
}
.carousel,
.carousel img {
height: 300px !important;
width: 100%;
}
</style>
</head>
<body>
<div class="focus">
<div id="carousel-example-generic" class="carousel slide" data-ride="carousel">
<!-- Indicators 小圆点-->
<ol class="carousel-indicators">
<li data-target="#carousel-example-generic" data-slide-to="0" class="active"></li>
<li data-target="#carousel-example-generic" data-slide-to="1"></li>
<li data-target="#carousel-example-generic" data-slide-to="2"></li>
</ol>
<!-- Wrapper for slides 轮播图片-->
<div class="carousel-inner" role="listbox">
<div class="item active">
<img src="upload/banner(1).dpg" alt="...">
<div class="carousel-caption">
pic1
</div>
</div>
<div class="item">
<img src="upload/banner1.dpg" alt="...">
<div class="carousel-caption">
pic2
</div>
</div>
<div class="item">
<img src="upload/banner2.dpg" alt="...">
<div class="carousel-caption">
pic3
</div>
</div>
</div>
<!-- Controls 左右箭头-->
<a class="left carousel-control" href="#carousel-example-generic" role="button" data-slide="prev">
<span class="glyphicon glyphicon-chevron-left" aria-hidden="true"></span>
<span class="sr-only">Previous</span>
</a>
<a class="right carousel-control" href="#carousel-example-generic" role="button" data-slide="next">
<span class="glyphicon glyphicon-chevron-right" aria-hidden="true"></span>
<span class="sr-only">Next</span>
</a>
</div>
</div>
<script>
$('.carousel').carousel({
interval: 1000
})
</script>
</body>
</html>
Bootstrap
Bootstrap是一个简洁、直观、强悍的前端开发框架,它让web开发更加迅速、简单。能开发PC端,也能开发移动端。
Bootstrap JS插件使用步骤:
- 引入相关JS文件
- 复制HTML结构
- 修改对应样式
- 修改相应JS参数
引入JS和CSS文件
首先引入js和css文件
<!-- 引入bootstrap 样式文件 -->
<link rel="stylesheet" href="bootstrap/css/bootstrap.min.css">
<!-- 引入我们自己的首页样式文件 -->
<link rel="stylesheet" href="css/index.css">
<!-- 先引入jquery js文件 -->
<script src="bootstrap/js/jquery.min.js"></script>
然后找到轮播图的位置,将刚刚练习过的轮播图HTML放进去
然后在css中修改图片还有左右箭头的位置
.carousel,
.carousel img {
width: 100%;
height: 266px!important;
}
还有修改一系列相关样式
本地存储
本地存储
随着互联网的快速发展,基于网页的应用越来越普遍,同时也变得越来越复杂,为了满足各种各样的需求,会经常性的在本地存储大量的数据,HTML5规范提出了相关的解决方案。
本地存储特性
- 数据存储在用户浏览器中
- 设置、读取方便、甚至页面刷新不丢失数据
- 容量较大,sessionStorage约5M、localStorage约20M
- 只能存储字符串,可以将对象JSON.stringify()编码后存储
window.sessionStorage
按F12,在application里面的session storage里面进行交互
步骤:
- 生命周期是通过关闭浏览器窗口结束
- 在同一个窗口(页面)下的数据可以共享
- 以键值对的形式存储使用
存储数据
sessionStorage.setItem(key, value)
// key是自己起的名字,value是其值
获取数据
sessionStorage.getItem(key)
删除所有数据
sessionStorage.clear()
<input type="text" name="" id="">
<button class="set">存储数据</button>
<button class="get">获取数据</button>
<button class="remove">删除数据</button>
<button class="del">清空所有数据</button>
<script>
var ipt = document.querySelector('input');
var set = document.querySelector('.set');
set.addEventListener('click', function () {
// 当我们点击了之后,就可以把表单里面的值存储起来
var val = ipt.value;
window.sessionStorage.setItem('uname', val);
window.sessionStorage.setItem('mingzi', val);
});
var get = document.querySelector('.get');
get.addEventListener('click', function () {
// 当我们点击了之后,就可以得到相应的值
sessionStorage.getItem('uname');
sessionStorage.getItem('mingzi')
});
var remove = document.querySelector('.remove');
remove.addEventListener('click', function () {
// 当我们点击了之后,就可以删除相应的值
sessionStorage.removeItem('uname');
});
var del = document.querySelector('.del');
del.addEventListener('click', function () {
// 当我们点击了之后,就可以删除所有的数据
sessionStorage.clear();
})
</script>
window.localStorage
- 生命周期永久有效,除非手动删除否则关闭页面也会存在
- 可以多窗口(页面)共享(同一浏览器可以共享)
- 以键值对的形式存储使用
存储数据
localStorage.setItem(key, value)
// key是自己起的名字,value是其值
获取数据
localStorage.getItem(key)
删除数据
localStorage.removeItem(key)
删除所有数据
localStorage.clear()
以上基本和sessionStorage相同
一案例:
案例分析:
- 把数据存起来,用到本地存储
- 关闭页面,也可以显示用户名,所以用到localStorage
- 打开页面,先判断是否有这个用户名,如果有,就在表单里显示用户名,并且勾选复选框
- 当复选框发生改变的时候change事件
- 如果勾选,就存储,否则就移除
用户名:
<input type="text" id="username">
<input type="checkbox" name="" id="remember">是否记住用户名
<script>
var username = document.querySelector('#username');
var remember = document.querySelector('#remember');
if (localStorage.getItem('username')) {
username.value = localStorage.getItem('username');
remember.checked = true;
}
remember.addEventListener('change', function () {
if (this.checked) {
localStorage.setItem('username', username.value);
} else {
localStorage.removeItem('username');
}
})
</script>