移动端网页特效
1.触摸事件
touch对象代表这样一个触摸点
常见触摸事件:
触摸touch事件 | 说明 |
---|---|
touchstart | 手指触摸到一个 DOM 元素触发 |
touchmove | 手指在一个 DOM 元素上滑动时触发 |
touchend | 手指从一个 DOM 元素上移开时触发 |
2.触摸事件对象
TouchEvent 是一类描述手指在触摸平面的状态变化的事件
touchstart、touchmove、touchend 三个事件都会各自有事件对象
触摸事件对象三个常见对象列表:
触摸列表 | 说明 |
---|---|
touches | 正在触摸屏幕的所有手指的一个列表 |
targetTouches | 正在触摸当前 DOM 元素上的手指的一个列表 |
changedTouches | 手指状态发生了改变的列表,从无到有,从有到无变化 |
3.移动端拖动元素
(1) touchstart、touchmove、touchend 可以实现拖动元素
(2)拖动元素需要当前手指的坐标值,可以使用targetTouches[0]里面的 pageX和 pageY
(3)移动端拖动原理:手指移动中,计算出手指移动的距离。然后用盒子原来的位置+手指移动的距离
(4)手指移动的距离 = 手指滑动的位置 - 手指刚触摸的位置
拖动元素三部曲:
(1)触摸元素touchstart:获取手指初始坐标,同时获得盒子原来的位置
(2)移动手指touchmove:计算手指的滑动距离,并且移动盒子
(3)离开手指touchend:
手指移动会触发滚动屏幕,要阻止默认的屏幕滚动e.preventDefault();
例子:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no,
initial-sale=1.0, maximum-scale=1.0, minimum-scale=1.0"/>
<title></title>
<style>
div {
position: absolute;
left: 0;
width: 100px;
height: 100px;
background-color: pink;
}
</style>
</head>
<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;
div.addEventListener('touchstart', function(e) {
// 获取手指初始坐标
startX = e.targetTouches[0].pageX;
startY = e.targetTouches[0].pageY;
x = this.offsetLeft;
y = this.offsetTop;
});
div.addEventListener('touchmove', function(e) {
// 计算手指的移动距离: 手指移动之后的坐标减去手指初始的坐标
var moveX = e.targetTouches[0].pageX - startX;
var moveY = e.targetTouches[0].pageY - startY;
// 移动我们的盒子 盒子原来的位置 + 手指移动的距离
this.style.left = x + moveX + 'px';
this.style.top = y + moveY + 'px';
e.preventDefault(); // 阻止屏幕滚动的默认行为
});
</script>
</body>
</html>
效果图如下:
4.移动端常见特效
(1)移动端轮播图
和PC端轮播图一样
1. 自动播放轮播图
2. 手指可以拖动轮播图
我们补充学习一个属性classList属性
classList属性返回元素的类名,ie10版本以上支持
该属性用于元素添加,移除及其切换CSS类,有以下方法
添加类:
element.classList.add('类名');
不会覆盖以前的类名,是在后面追加类名,类名前面不需要加.
删除类:
element.classList.remove('类名');
切换类:
element.classList.toggle('类名');
我们可以先做个案例:开关灯
代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no,
initial-sale=1.0, maximum-scale=1.0, minimum-scale=1.0"/>
<title></title>
<style>
.bg {
background-color: black;
}
</style>
</head>
<body>
<div></div>
<button> 开关灯</button>
<script>
// classList 返回元素的类名
var div = document.querySelector('div');
// 切换类
var btn = document.querySelector('button');
btn.addEventListener('click', function() {
document.body.classList.toggle('bg');
})
</script>
</body>
</html>
好了,有了这个属性做圆点跟随变化效果就容易多了,上代码
html代码:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no,
initial-sale=1.0, maximum-scale=1.0, minimum-scale=1.0"/>
<!-- 引入初始化文件 -->
<link rel="stylesheet" href="css/normalize.css" />
<!-- 引入首页样式-->
<link rel="stylesheet" href="css/index.css" />
<script src="js/index.js"></script>
<script src="js/animate.js"></script>
<title>携程网首页</title>
</head>
<body>
<!--焦点图某块-->
<div class="focus">
<ul>
<li><img src="upload/focus3.jpg" alt=""></li>
<li><img src="upload/focus1.jpg" alt=""></li>
<li><img src="upload/focus2.jpg" alt=""></li>
<li><img src="upload/focus3.jpg" alt=""></li>
<li><img src="upload/focus1.jpg" alt=""></li>
</ul>
<!-- 小圆点 -->
<ol>
<li class="current"></li>
<li></li>
<li></li>
</ol>
</div>
</body>
</html>
css代码:
body{
max-width: 540px;
min-width: 320px;
margin: 0 auto;
font: normal 14px/1.5 tahoma,"lucida grande",verdana,"microsoft
yahei",stxihei,hei;
color: #000;
background: #f2f2f2;
overflow-x: hidden;
-webkit-tap-highlight-color: transparent;
height: 1000px;
}
a{
text-decoration: none;
color: #222;
}
div{
box-sizing: border-box;
}
ul,ol{
list-style: none;
margin: 0;
padding: 0;
}
/* 焦点图模块 */
.focus {
position: relative;
overflow: hidden;
}
.focus img {
width: 100%;
}
.focus ul{
width: 500%;
overflow: hidden;
margin-left: -100%;
}
.focus ul li{
float: left;
width: 20%;
}
.focus ol {
position: absolute;
bottom: 5px;
right: 5px;
margin: 0px;
}
.focus ol li {
display: inline-block;
width: 5px;
height: 5px;
background-color: red;
border-radius: 2px;
transition: all .3s;
}
.focus .current{
width: 15px;
}
js代码:
window.addEventListener('load', function(){
// 1. 获取元素
var focus = document.querySelector('.focus');
var ul = focus.children[0];
// 获得focus 的宽度
var w = focus.offsetWidth;
var ol = focus.children[1];
// 2. 利用定时器自动轮播图图片
var index = 0;
var timer = setInterval(function() {
index++;
var translatex = -index * w;
ul.style.transition = 'all .3s';
ul.style.transform = 'translateX(' + translatex + 'px)';
}, 2000);
//无缝滚动
ul.addEventListener('transitionend', function(){
if(index >= 3){
index = 0;
// 去掉过渡效果 这样让我们的ul 快速的跳到目标位置
ul.style.transition = 'none';
var translatex = -index * w;
ul.style.transform = 'translateX(' + translatex + 'px)';
}else if(index < 0){
index = 2;
ul.style.transition = 'none';
var translatex = -index * w;
ul.style.transform = 'translateX(' + translatex + 'px)';
}
// 3. 小圆点跟随变化
// 把ol里面li带有current类名的选出来去掉类名 remove
ol.querySelector('.current').classList.remove('current');
// 让当前索引号 的小li 加上 current add
ol.children[index].classList.add('current');
})
})
一个大致完整的不加拖拽的移动端轮播图效果:
下面我们做拖拽效果,可以手动左右拉动轮播图
js代码
// 4. 手指滑动轮播图
// 触摸元素 touchstart: 获取手指初始坐标
var startX = 0;
var moveX = 0; // 后面我们会使用这个移动距离所以要定义一个全局变量
ul.addEventListener('touchstart', function(e) {
startX = e.targetTouches[0].pageX;
// 手指触摸的时候就停止定时器
clearInterval(timer);
});
// 移动手指 touchmove: 计算手指的滑动距离, 并且移动盒子
ul.addEventListener('touchmove', function(e) {
// 计算移动距离
moveX = e.targetTouches[0].pageX - startX;
// 移动盒子: 盒子原来的位置 + 手指移动的距离
var translatex = -index * w + moveX;
// 手指拖动的时候,不需要动画效果所以要取消过渡效果
ul.style.transition = 'none';
ul.style.transform = 'translateX(' + translatex + 'px)';
e.preventDefault(); // 阻止滚动屏幕的行为
});
// 手指离开 根据移动距离去判断是回弹还是播放上一张下一张
ul.addEventListener('touchend', function(e) {
// (1) 如果移动距离大于50像素我们就播放上一张或者下一张
if (Math.abs(moveX) > 50) {
// 如果是右滑就是 播放上一张 moveX 是正值
if (moveX > 0) {
index--;
} else {
// 如果是左滑就是 播放下一张 moveX 是负值
index++;
}
var translatex = -index * w;
ul.style.transition = 'all .3s';
ul.style.transform = 'translateX(' + translatex + 'px)';
} else {
// (2) 如果移动距离小于50像素我们就回弹
var translatex = -index * w;
ul.style.transition = 'all .1s';
ul.style.transform = 'translateX(' + translatex + 'px)';
}
// 手指离开的时候就重新开启定时器
clearInterval(timer);
timer = setInterval(function() {
index++;
var translatex = -index * w;
ul.style.transition = 'all .3s';
ul.style.transform = 'translateX(' + translatex + 'px)';
}, 2000);
});
效果图如下:
可以再加一个全局变量flag优化代码,如果触摸不移动就不计算后面的逻辑
js代码:
// 4. 手指滑动轮播图
// 触摸元素 touchstart: 获取手指初始坐标
var startX = 0;
var moveX = 0; // 后面我们会使用这个移动距离所以要定义一个全局变量
var flag = false;
ul.addEventListener('touchstart', function(e) {
startX = e.targetTouches[0].pageX;
// 手指触摸的时候就停止定时器
clearInterval(timer);
});
// 移动手指 touchmove: 计算手指的滑动距离, 并且移动盒子
ul.addEventListener('touchmove', function(e) {
// 计算移动距离
moveX = e.targetTouches[0].pageX - startX;
// 移动盒子: 盒子原来的位置 + 手指移动的距离
var translatex = -index * w + moveX;
// 手指拖动的时候,不需要动画效果所以要取消过渡效果
ul.style.transition = 'none';
ul.style.transform = 'translateX(' + translatex + 'px)';
flag = true; // 如果用户手指移动过我们再去判断否则不做判断效果
e.preventDefault(); // 阻止滚动屏幕的行为
});
// 手指离开 根据移动距离去判断是回弹还是播放上一张下一张
ul.addEventListener('touchend', function(e) {
if(flag){
// (1) 如果移动距离大于50像素我们就播放上一张或者下一张
if (Math.abs(moveX) > 50) {
// 如果是右滑就是 播放上一张 moveX 是正值
if (moveX > 0) {
index--;
} else {
// 如果是左滑就是 播放下一张 moveX 是负值
index++;
}
var translatex = -index * w;
ul.style.transition = 'all .3s';
ul.style.transform = 'translateX(' + translatex + 'px)';
} else {
// (2) 如果移动距离小于50像素我们就回弹
var translatex = -index * w;
ul.style.transition = 'all .1s';
ul.style.transform = 'translateX(' + translatex + 'px)';
}
}
// 手指离开的时候就重新开启定时器
clearInterval(timer);
timer = setInterval(function() {
index++;
var translatex = -index * w;
ul.style.transition = 'all .3s';
ul.style.transform = 'translateX(' + translatex + 'px)';
}, 2000);
});
这样,我们完美严谨的移动端轮播图就做好啦
5.移动端常用插件
(1)fastclick插件的使用
300ms延迟问题
一般情况下,如果没有经过特殊处理,移动端浏览器在派发点击事件的时候,通常会出现300ms左右的延迟,也就是说,当我们点击页面的时候移动端浏览器并不是立即作出反应,而是会等上一小会儿才会出现点击的效果
(1)fastclick 插件解决 300ms延迟问题
Github官网地址链接: https://github.com/ftlabs/fastclick.
(2)插件的使用
1. 引入js文件
进入链接,lib文件里的fastclick.js文件复制
2. 使用方法
代码如下:
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title></title>
<script src="fastclick.js"></script>
</head>
<body>
<script>
if ('addEventListener' in document) {
document.addEventListener('DOMContentLoaded', function() {
FastClick.attach(document.body);
}, false);
}
</script>
</body>
</html>
引入后所有元素都没有延迟问题了,用户体验度会更好!
(2)Swiper插件的使用
中文官网链接: https://www.swiper.com.cn/.
引入插件
下载解压后,dist文件里有css和js
按照语法使用
demo里有很多案例,可以复制模板使用,还有引入css、js路径
做个搞心态的轮播图,还有很多很多页面,根据需求选择
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no,
initial-sale=1.0, maximum-scale=1.0, minimum-scale=1.0"/>
<title></title>
<link rel="stylesheet" type="text/css" href="swiper.min.css"/>
<link rel="stylesheet" type="text/css" href="index.css"/>
<script src="swiper.min.js"></script>
<script src="index.js"></script>
</head>
<body>
<!-- Swiper -->
<div class="swiper-container">
<div class="swiper-wrapper">
<div class="swiper-slide">Slide 1</div>
<div class="swiper-slide">Slide 2</div>
<div class="swiper-slide">Slide 3</div>
<div class="swiper-slide">Slide 4</div>
</div>
<!-- Add Pagination -->
<div class="swiper-pagination"></div>
</div>
</body>
</html>
还有其他好用的插件
https://http://www.superslide2.com/.
https://github.com/cubiq/iscroll.
6.移动端常用开发框架
前端常用框架:Bootstrap、Vue、Angular、React
7.本地存储
(1)特性
1.数据存储在用户浏览器中
2.设置、读取方便、页面刷新不会丢失数据
3.容量较大,sessionStorage 大约5M、localStorage 大约20M
4.只能存字符串,可以将对象JSON.stringify()编码后存储
(2)window.sessionStorage
1.生命周期为关闭浏览器窗口
2.在同一窗口下数据可以共享
3.以键值对的形式存储使用
存储数据:
sessionStorage.setItem(key,value)
获取数据:
sessionStorage.getItem(key)
删除数据:
sessionStorage.removeItem(key)
删除所有数据:
sessionStorage.clear()
例子
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no,
initial-sale=1.0, maximum-scale=1.0, minimum-scale=1.0"/>
<title></title>
</head>
<body>
<input type="text">
<button class="set">存储数据</button>
<button class="get">获取数据</button>
<button class="remove">删除数据</button>
<button class="del">清空所有数据</button>
<script>
console.log(localStorage.getItem('username'));
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');
set.addEventListener('click', function() {
// 当我们点击了之后,就可以把表单里面的值存储起来
var val = ipt.value;
sessionStorage.setItem('uname', val);
sessionStorage.setItem('pwd', val);
});
get.addEventListener('click', function() {
// 当我们点击了之后,就可以把表单里面的值获取过来
console.log(sessionStorage.getItem('uname'));
});
remove.addEventListener('click', function() {
//
sessionStorage.removeItem('uname');
});
del.addEventListener('click', function() {
// 当我们点击了之后,清除所有的
sessionStorage.clear();
});
</script>
</body>
</html>
(3)window.localStorage
1.生命周期永久有效除非手动删除,否则关闭页面也会存在
2.可以多窗口共享
3.以键值对的形式存储使用
存储数据:
localStorage.setItem(key,value)
获取数据:
localStorage.getItem(key)
删除数据:
localStorage.removeItem(key)
删除所有数据:
localStorage.clear()
案例:记住用户名
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, user-scalable=no,
initial-sale=1.0, maximum-scale=1.0, minimum-scale=1.0"/>
<title></title>
</head>
<body>
<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>
</body>
</html>