JS BOM 和 DOM 学习第六天
今日学习目标
- 移动端网页特效
1. 触屏事件
1.1 触屏事件概述
-
浏览器兼容性:移动端浏览器有较好的兼容性,可以放心使用原生js书写代码
-
移动端的特点:有触屏事件(touch)
-
touch对象代表一个触摸点
-
常见触屏事件
触屏事件 | 说明 |
---|---|
touchstart | 手指触摸到一个DOM元素触发 |
touchmove | 手指在一个DOM元素上滑动触发 |
touchend | 手指从一个DOM元素上移开时触发 |
示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
div{
height: 200px;
width: 200px;
background-color: pink;
}
</style>
</head>
<body>
<div></div>
<script>
var div=document.querySelector('div');
// 1.手指触摸事件
div.addEventListener('touchstart',function(){
console.log('手指开始触摸');
})
// 2.手指持续触摸
div.addEventListener('touchmove',function(){
console.log('手指持续触摸');
})
// 3. 手指移开
div.addEventListener('touchend',function(){
console.log('手指离开');
})
</script>
</body>
</html>
- 效果图
1.2 触屏事件对象(TouchEvent)
-
touchstart,touchmove,touchend都有各自的事件对象
-
常用的对象列表
触摸列表 说明 touches 正在触摸屏幕的所有手指的一个列表 targetTouches 正在触摸当前DOM元素的手指的一个列表 changedTouches 手指状态发生变化的列表,如从无到有,或者从有到无
示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
div{
height: 200px;
width: 200px;
background-color: pink;
}
</style>
</head>
<body>
<div></div>
<script>
var div=document.querySelector('div');
// 1.手指触摸事件
div.addEventListener('touchstart',function(e){
// console.log('手指开始触摸');
// 1.打印所有手指列表
console.log(e.touches);
// 2.打印所有正在触摸DOM元素的手指列表
console.log(e.targetTouches);
// 3. 打印状态发生变化的手指列表
console.log(e.changedTouches);
})
// 2.手指持续触摸
div.addEventListener('touchmove',function(){
// console.log('手指持续触摸');
})
// 3. 手指移开
div.addEventListener('touchend',function(e){
// console.log('手指离开');
// 3.当手指离开时,只有changedTouches的列表中有值
console.log(e.touches);
console.log(e.targetTouches);
console.log(e.changedTouches);
})
</script>
</body>
</html>
- 效果图
1.3 移动端拖动元素
- 思路
示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
div{
position: absolute;
width: 100px;
height: 100px;
background-color: pink;
}
</style>
</head>
<body>
<div></div>
<script>
var div=document.querySelector('div');
// 1.获取鼠标当前位置
var mouseX=0;
var mouseY=0;
// 2.获取盒子当前的位置
var boxX=0;
var boxY=0;
// 获取起始坐标
div.addEventListener('touchstart',function(e){
// 获取触摸时的起始坐标
mouseX=e.targetTouches[0].pageX;
mouseY=e.targetTouches[0].pageY;
boxX=this.offsetLeft;
boxY=this.offsetTop;
})
div.addEventListener('touchmove',function(e){
// 手指移动,获取实时坐标
var moveX=e.targetTouches[0].pageX-mouseX;
var moveY=e.targetTouches[0].pageY-mouseY;
// 盒子移动
console.log(boxX);
console.log(moveX);
this.style.left=boxX+moveX+'px';
this.style.top=boxY+moveY+'px';
// 阻止屏幕滚动的默认行为
e.preventDefault();
})
</script>
</body>
</html>
- 效果图
注意点
- 这里的手指移动会冒泡触发屏幕滚动,需要设置e.preventDefault(),阻止冒泡
2. 移动端常见特效
2.1 clsssList属性
- h5新增属性,返回元素的类名,ie10以上支持
- 用于在元素中添加,移除和切换CSS类,有以下方法
方法 | 使用 |
---|---|
添加类 | element.classList.add(‘类名’) |
移除类 | element.classList.remove(‘类名’) |
切换类 | element.classList.toggle(‘类名’) |
- 切换类的说明:如果当前元素存在括号里的类名,则去除该类名,如果不存在,则添加类名
示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<style>
.bg{
background-color: #000;
}
</style>
</head>
<body>
<button>开关灯</button>
<div class="one two three"></div>
<script>
var div=document.querySelector('div');
// 获取类名伪数组,classList,ie10以上支持
console.log(div.classList);
// 通过数组方法获取各个类名
for(var i=0;i<div.classList.length;i++){
console.log(div.classList[i]);
}
// 添加类名
div.classList.add('four');
// 移除类名
div.classList.remove('one');
console.log(div.classList);
// 切换类名,切换一次(如果类名存在,则去除类名,类名不存在,则添加类名)
var btn=document.querySelector('button');
btn.addEventListener('click',function(){
// 切换类名
document.body.classList.toggle('bg');
})
</script>
</body>
</html>
- 效果图
2.2 移动端轮播图
移动端轮播图与pc端区别
- 移动端兼容性好,一些好方法可以使用
- 移动端需要额外两张图片,pc端额外一张
- pc端为左右点击按钮,移动端手指滑动
开发思路
示例
- 轮播图html
<!-- banner图区域 -->
<div class="banner">
<ul>
<li><a href="#"><img src="./uploads/item_2.png" alt=""></a></li>
<li><a href="#"><img src="./uploads/item_3.png" alt=""></a></li>
<li><a href="#"><img src="./uploads/item_4.png" alt=""></a></li>
</ul>
<ol>
</ol>
</div>
- 轮播图less
// banner图区域,最好指定一下高度,为后面小原点定位不偏
.banner{
position: relative;
height: (160/@rootsize);
// overflow: visible;
overflow: hidden;
ul{
width: 600%;
height: 100%;
// 为了显示第二张图片
margin-left: -100%;
li{
display: block;
width: (375/@rootsize);
float: left;
margin: 0;
padding: 0;
}
}
ol{
margin: 0;
padding: 0;
list-style: none;
z-index: 100;
position: absolute;
left: 50%;
transform: translateX(-50%);
bottom: (5/@rootsize);
height: (18/@rootsize);
border-radius: (9/@rootsize);
li{
float: left;
width: (12/@rootsize);
height: (12/@rootsize);
margin: (3/@rootsize);
border-radius: 50%;
border: 1px solid #fff;
box-sizing: border-box;
// background-color: #fff;
}
.current{
background-color: #fff;
}
}
}
- 轮播图js
window.addEventListener('load',function(){
// alert(11);
var banner=this.document.querySelector('.banner');
// console.log(banner);
var ul=banner.querySelector('ul');
var ol=banner.querySelector('ol');
// 循环创建轮播小圆点
for(var i=0;i<ul.children.length;i++){
var li=this.document.createElement('li');
li.setAttribute('index',i);
ol.appendChild(li);
}
// 第一张图片设置current属性
ol.children[0].className='current';
// 移动端与pc端的无缝轮播有区别,防止第一张左滑留白,第一张前面也添加一张图片
var copy1=ul.children[0].cloneNode(true);
var copy2=ul.children[ul.children.length-1].cloneNode(true);
ul.appendChild(copy1);
ul.insertBefore(copy2,ul.children[0]);
// 设置图片自动滚动,定时器+css3的位移(translate)
// 获取焦点图盒子的大小
var b_width=banner.clientWidth;
// console.log(b_width);
var index=0;
var timer=this.setInterval(function(){
index++;
// 设置transform过渡
ul.style.transition='all .3s';
ul.style.transform='translateX('+(-b_width*index) +'px)'
},2000);
// 判断过渡是否完成,如果完成,在执行操作
ul.addEventListener('transitionend', function() {
// 无缝滚动
if (index >= 3) {
index = 0;
// console.log(index);
// 去掉过渡效果 这样让我们的ul 快速的跳到目标位置
ul.style.transition = 'none';
// 利用最新的索引号乘以宽度 去滚动图片
var translatex = -index * b_width;
ul.style.transform = 'translateX(' + translatex + 'px)';
} else if (index < 0) {
index = 2;
ul.style.transition = 'none';
// 利用最新的索引号乘以宽度 去滚动图片
var translatex = -index * b_width;
ul.style.transform = 'translateX(' + translatex + 'px)';
}
// 在过渡接收后检测小圆点的变化
// 去除当前的小圆点,实现小圆点切换
ol.querySelector('li.current').classList.remove('current');
ol.children[index].classList.add('current');
})
// 手指滑动实现轮播图切换
var mouseX=0;
var moveX=0;
var liStep=ul.children[0].clientWidth/7;
// 定义一个变量判断用户是否移动
var touch=false;
ul.addEventListener('touchstart',function(e){
// 手指摸上去,停止计时器
clearInterval(timer);
timer=null;
mouseX=e.targetTouches[0].pageX;
})
// 手指滑动轮播图
ul.addEventListener('touchmove',function(e){
// 鼠标的移动距离
moveX=e.targetTouches[0].pageX-mouseX;
// translateX的距离
var translatex=(-b_width*index)+moveX;
ul.style.transform = 'translateX(' + translatex + 'px)';
touch=true;
// 取消默认滚动屏幕行为
e.preventDefault();
})
ul.addEventListener('touchend',function(){
if(touch){
if(Math.abs(moveX)>liStep){
// 大于0,播放上一张
if(moveX>0){
index--;
}else if(moveX<0){
// 播放下一张
index++;
}
}
var translatex=-index*b_width;
ul.style.transition='all .3s';
ul.style.transform = 'translateX(' + translatex + 'px)';
}
// 手指离开,定时器开始
timer=setInterval(function(){
index++;
// 设置transform过渡
ul.style.transition='all .3s';
ul.style.transform='translateX('+(-b_width*index) +'px)'
},2000);
})
})
- 效果图
2.3 click延时解决方案
-
移动端click事件会有300ms的延时,原因是移动端屏幕双击会缩放(double tap to zoom)
-
解决方案
- 禁用缩放。浏览器禁用默认的双击缩放行为并且去掉300ms的点击延时
- 利用touch事件封装这个事件解决300ms的延迟
-
原理
- 封装函数
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
//封装tap,解决click 300ms 延时
function tap (obj, callback) {
var isMove = false;
var startTime = 0; // 记录触摸时候的时间变量
obj.addEventListener('touchstart', function (e) {
startTime = Date.now(); // 记录触摸时间
});
obj.addEventListener('touchmove', function (e) {
isMove = true; // 看看是否有滑动,有滑动算拖拽,不算点击
});
obj.addEventListener('touchend', function (e) {
if (!isMove && (Date.now() - startTime) < 150) { // 如果手指触摸和离开时间小于150ms 算点击
callback && callback(); // 执行回调函数
}
isMove = false; // 取反 重置
startTime = 0;
});
}
//调用
tap(div, function(){
// 执行回调函数
});
</script>
</body>
</html>
2.4 fastclick 插件
2.4.1 插件的使用
- 引入js文件
- 根据语法规范使用js文件
- 引入js文件后的操作:在新的script标签中加入该代码
if ('addEventListener' in document) {
document.addEventListener('DOMContentLoaded', function() {
FastClick.attach(document.body);
}, false);
}
2.5 swiper 插件(轮播图插件)
-
使用方法
- 引入插件
<!-- 引入swiper js 文件 --> <script src="js/swiper.min.js"></script> <!-- 引入我们自己的js文件 --> <script src="js/index.js"></script>
- 复制demo中的html结构
<!-- Swiper 注意不要更改里面的结构和类名 --> <div class="swiper-container"> <div class="swiper-wrapper"> <div class="swiper-slide"> <img src="upload/banner.dpg" alt=""> </div> <div class="swiper-slide"> <img src="upload/banner1.dpg" alt=""> </div> <div class="swiper-slide"> <img src="upload/banner2.dpg" alt=""> </div> <div class="swiper-slide"> <img src="upload/banner3.dpg" alt=""> </div> </div> <!-- Add Pagination --> <div class="swiper-pagination"></div>
- 复制相关的css样式
.swiper-slide { text-align: center; font-size: 18px; background: #fff; /* Center slide text vertically */ display: -webkit-box; display: -ms-flexbox; display: -webkit-flex; display: flex; -webkit-box-pack: center; -ms-flex-pack: center; -webkit-justify-content: center; justify-content: center; -webkit-box-align: center; -ms-flex-align: center; -webkit-align-items: center; align-items: center; } .swiper-pagination-bullet { background: #fff!important; }
- 复制相关的js样式
window.addEventListener('load', function() { var swiper = new Swiper('.swiper-container', { spaceBetween: 30, centeredSlides: true, autoplay: { delay: 5000, disableOnInteraction: false, }, pagination: { el: '.swiper-pagination', clickable: true, }, navigation: { nextEl: '.swiper-button-next', prevEl: '.swiper-button-prev', }, }); })
使用方法查阅
2.6 其他移动端常见插件
-
superslide:<SuperSlide | TouchSlide 官方网站 大话主席 (superslide2.com)>(网页各种效果)
-
iscroll:<GitHub - cubiq/iscroll:平滑的网络滚动>(轮播图)
2.7 移动端视频插件(zy.media.js)
- h5新增视频标签,但浏览器的支持情况不同
- 支持格式可由source解决
- 而播放器的样式,外观在不同的浏览器会有不同的结果
- 解决方案
- 使用zy.media.js插件,实现效果的统一
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<!-- 引入样式表 -->
<link rel="stylesheet" href="./zy.media.min.css">
<!-- 复制样式 -->
<style type="text/css">
#modelView {
background-color: #DDDDDD;
z-index: 0;
opacity: 0.7;
height: 100%;
width: 100%;
position: relative;
}
.playvideo {
padding-top: auto;
z-index: 9999;
position: relative;
width: 300px;
height: 200px;
}
.zy_media {
z-index: 999999999
}
</style>
</head>
<body>
<!-- 复制视频盒子 -->
<div class="playvideo">
<div class="zy_media">
<video data-config='{"mediaTitle": "测试视频--视频"}'>
<source src="mov.mp4" type="video/mp4">
您的浏览器不支持HTML5视频
</video>
</div>
<div id="modelView"> </div>
</div>
<!-- 1.引入js插件 -->
<script src="zy.media.min.js"></script>
<script>
zymedia('video', {
autoplay: true
});
</script>
</body>
</html>
- 效果图
4. 移动端常用开发框架
- Bootstrap复习
示例(轮播图)
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<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;
}
.carousel .item img,
.carousel {
width: 100%;
height: 300px;
}
</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>
<li data-target="#carousel-example-generic" data-slide-to="3"></li>
</ol>
<!-- Wrapper for slides -->
<div class="carousel-inner" role="listbox">
<div class="item active">
<img src="./upload/banner1.jpg" alt="...">
<div class="carousel-caption">
...
</div>
</div>
<div class="item">
<img src="./upload/banner2.jpg" alt="...">
<div class="carousel-caption">
...
</div>
</div>
<div class="item">
<img src="./upload/banner3.jpg" alt="...">
<div class="carousel-caption">
...
</div>
</div>
<div class="item">
<img src="./upload/banner(1).jpg" alt="...">
<div class="carousel-caption">
...
</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>
- 效果图
5. 本地存储
5.1 本地存储的特点
- 数据存储在用户浏览器中
- 设置,读取数据方便,页面刷新数据不丢失
- 容量大,sessionStorage容量为5m,localStorage容量为20m
- 只能存储字符串,可以将对象JSON.stringify()后存储
5.2 window.sessionStorage
- 特点
- 生命周期为浏览器窗口关闭
- 同一个窗口数据可共享
- 以键值对形式存储
操作 | 用法 |
---|---|
存储数据 | sessionStorage.setItem(key,value) |
获取数据 | sessionStorage.getItem(key) |
移除数据 | sessionStorage.removeItem(key) |
清空数据(谨慎使用) | sessionStorage.clear() |
示例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="text">
<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');
var get = document.querySelector('.get');
var remove = document.querySelector('.remove');
var del = document.querySelector('.del');
// 1.存储数据
set.addEventListener('click', function() {
sessionStorage.setItem('uname', ipt.value);
sessionStorage.setItem('psw', ipt.value);
})
// 2.获取数据
get.addEventListener('click', function() {
var aData = sessionStorage.getItem('uname');
console.log(aData);
})
// 3. 移除数据,这里是一次删除一条,可以设置实现删除多条
remove.addEventListener('click', function() {
sessionStorage.removeItem('uname');
})
// 4.清空所有数据
del.addEventListener('click', function() {
sessionStorage.clear();
})
</script>
</body>
</html>
- 效果图
5.3 window.localStorage
特点
- 生命周期永久生效,除非手动删除,否则关闭页面也会存在
- 可以多窗口(页面)共享
- 键值对存储
操作 | 用法 |
---|---|
存储数据 | localStorage.setItem(key,value) |
获取数据 | localStorage.getItem(key) |
移除数据 | localStorage.removeItem(key) |
清空数据(谨慎使用) | localStorage.clear() |
示例
- localStorage使用
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="text">
<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');
var get = document.querySelector('.get');
var remove = document.querySelector('.remove');
var del = document.querySelector('.del');
// 1.存储数据
set.addEventListener('click', function() {
localStorage.setItem('uname', ipt.value);
localStorage.setItem('psw', ipt.value);
})
// 2.获取数据
get.addEventListener('click', function() {
var aData = localStorage.getItem('uname');
console.log(aData);
})
// 3. 移除数据,这里是一次删除一条,可以设置实现删除多条
remove.addEventListener('click', function() {
localStorage.removeItem('uname');
})
// 4.清空所有数据
del.addEventListener('click', function() {
localStorage.clear();
})
</script>
</body>
</html>
- 数据共享测试
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script>
// 数据共享
var rtn = localStorage.getItem('uname');
console.log(rtn);
</script>
</body>
</html>
- 效果图
5.4 记住用户名案例
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="text" id="username"> <input type="checkbox" name="" id="remeber">记住用户名
<script>
var username = document.querySelector('#username');
var remeber = document.querySelector('#remeber');
console.log(username);
if (localStorage.getItem('username')) {
username.value = localStorage.getItem('username');
remeber.checked = true;
}
remeber.addEventListener('change', function() {
if (remeber.checked) {
localStorage.setItem('username', username.value);
} else {
localStorage.removeItem('username');
}
})
</script>
</body>
</html>
- 效果图