一、pc端网页特效
1、三大系列
- 元素偏移量offset系列
作用:使用offset系列相关属性可以动态的得到该元素的位置(偏移)、大小等
注意:
- 获得元素距离带有定位父元素的位置
- 获得元素自身的大小(宽度高度)
- 返回的数值不带单位
- 节点也可以返回父亲 返回的是最近一级的父亲 不管父亲有没有定位
属性:
属性 | 说明 |
element.offsetParent | 返回做为该元素带有定位的父级元素 如果父级都没有定位则返回body |
element.offsetTop | 返回元素相对带有定位父级元素上方的偏移 没有定位就是body |
element.offsetLeft | 返回元素相对带有父元素左边框的偏移 没有定位就是body |
element.offsetWidth | 返回自身包括padding、边框、内容区的宽度,返回数值不带单位 内边框、边框会撑大我们盒子的宽度 |
element.offsetHeight | 返回自身包括padding、边框、内容区的高度,返回数值不带单位 |
- 元素可视区client系列
作用:client相关属性来获取元素可视区的相关信息。可以动态的得到该元素的边框大小、元素大小等
属性:
属性 | 说明 |
element.clientTop | 返回元素上边框的大小 |
element.clientLeft | 返回元素左边框的大小 |
element.clientWidth | 返回自身包括padding、内容区的宽度,不包括边框,返回数值不带单位 |
element.clientHight | 返回自身包括padding、内容区的宽度,不包括边框,返回数值不带单位 |
- 元素滚动scroll系列
作用:相关属性可以动态的得到该元素的大小、滚动距离等,跟我们页面的滚动条有关
属性:
属性 | 说明 |
element.scrollTop | 返回被卷去的内容上侧距离,返回数值不带参数 |
element.scrollLeft | 返回被卷去的左侧距离。返回数值不带单位 |
element.scrollWidth | 返回自身实际的宽度,包括padding、不含边框。返回数值不带单位 |
element.scrollHeight | 返回自身实际的高度+scrollTop 包含padding、不含边框,返回数值不带单位 |
扩展内容:
onscroll滚动事件:如果浏览器的高度或宽度不足以显示整个页面时,会自动出现滚动条。当滚动条向下滚动时,页面上面被隐藏掉的高度,就是页面被卷去的头部 ,滚动条在滚动时会触发onscroll事件。
页面被卷去的头部:可以通过window.pageYOffset获得;如果声明了DTD使用document.documentElement.scrollTop;没有声明使用document.body.scrollTop 但是注意兼容的问题
页面被卷去的左侧:可以通过window.pageXOffset获得
三大系列总结:
1、offset和style的区别
- offset可以得到任意样式表中的样式值 || style只能得到行内样式表中的样式
- offset 系列获得的数值是没有单位的 || style.width 获得的是带有单位的字符串
- offsetWidth包含padding+border+width || style.width获得不包含padding和border值
- offsetWidth等属性是只读属性,只能获取不能赋值 || style.width是可读写属性,可以获得也可以读取
- 获得元素大小位置就使用offset || 给元素更改值 就用style改变
2、scroll和client的区别
- scroll返回的是我们真正的内容宽度 当内容超出盒子的时候 就会带上超出的宽度 || client相关属性来获取元素可视区的相关信息
2、立即执行函数:
立即执行函数 不需要调用,立马能够自己执行的函数
也可以传递参数
多个立即执行函数 之间用分号隔开
作用:独立创建了一个作用域 里面的所有变量都是局部变量,不存在命名冲突的情况
写法
写法一:
(function() { })() // 里面是一个匿名函数也可以起一个名字 第二个小括号可以看作调用函数 可以传递参数也可以不传递参数
比如:
(function sum(a,b){
console.log(a);
console.log(b);
})(1,2),
写法二:用法和上面的一样
(function(){ } ());
3、pageshow事件
pageshow事件是我们重新加载页面触发的事件
load也是重新加载(可以点链接、前进后退、f5强制刷新 都可以重新加载页面)火狐后退后不会重新加载页面
这个事件在页面显示时触发,无论页面是否来自缓存,在重新加载页面中,pageshow会在load事件触发后触发,根据事件对象中的persisted来判断是否是缓存中的页面触发的pageshow事件,这个事件给window添加
4、动画函数封装
作用:页面中可能有多个元素需要使用动画,不可能给每个元素写一个动画,所以就使用将动画用函数封装起来 谁使用谁就调用
核心原理:通过定时器setInterval()不断移动盒子的位置
实现步骤:
实现步骤:
- 获得盒子当前位置
- 让盒子在当前位置加上1个移动距离
- 利用定时器不断重复这个操作
- 加一个结束定时器的条件
- 注意:此元素需要添加定位,才能使用element.style.left
<script>
var div = document.querySelector('div');
var span = document.querySelector('span');
//obj目标对象 target移动距离
function animate(obj, target) {
var timer = setInterval(function () {
if (obj.offsetLeft <= target) {
obj.style.left = obj.offsetLeft + 1 + 'px';
} else {
clearInterval(timer); //当盒子的left值大于400后就停止计时器
}
}, 3)
}
animate(div,300);
animate(span,200);
</script>
动画函数简单的封装🌟
函数需要传递三个参数,动画对象和移动的距离和回调函数
语法:function animate(obj, target,callback) { } //动画函数封装
animate(span,200,function(){}); //调用
obj:动画对象-目标对象
target:移动的距离 - 目标位置
calback:回调函数
如果后面有回调函数就执行 否则不执行
写法一: if (callback()) {callback();
}
写法二: callback && callback(); //相当于短路运算符
存在的问题:
- 对每个目标对象开辟一个空间,如果有100个目标对象就会开辟100空间,非常占用空间
- 每个对象的定时器的名字一样
动画函数给不同元素记录不同定时器:
核心原理 :利用js是一门动态语言,可以很方便的给当前对象添加属性
如果多个元素都使用这个动画函数,每次都要var声明定时器,我们可以给不同的元素使用不同的定时器(自己专门用自己的定时器)
//利用对象,给对象添加一个属性
function animate(obj, target) {
obj.timer = setInterval(function () {
if (obj.offsetLeft <= target) {
obj.style.left = obj.offsetLeft + 1 + 'px';
} else {
clearInterval( obj.timer); //当盒子的left值大于400后就停止计时器
}
}, 3)
}
animate(div,300);
animate(span,200);
存在的问题:点击的越多开启定时器的就越来越多 速度就会越开越开
解决方案:在定时的前面添加 clearInterval(obj.timer)在调用定时器的时候先清楚一次定时器,将上次定时器清楚,避免重复调用
缓动动画:
原理:缓动动画就是让元素运动速度有所变化,最常见的是让速度慢慢停下来
思路:
- 让元素移动的距离慢慢变小
- 核心算法(目标值-现在的位置)/10 做为每次移动的距离 步长
- 停止的条件是:让当前盒子位置等于目标位置就停止定时器
注意:
obj.style.left = obj.offsetLeft + step +'px';
var step = (目标值-现在的位置)/10;
step = step>0?Math.ceil(step) : Math.floor(step);
注意js中有除法就避免不了有小数的计算,所以导致出现没有到达目标位置就停下来了 所以把我们的步长直改成整数,当step大于0就是往右的走,如果小于0就是往左走
我们可以将一个动画函数单独封装在一个js文件里,用的话就直接调用
function animate1(obj, target, callback) {
clearInterval(obj.timer); //在重复点击我们的按钮时 调用我们的定时器前面先清楚一次定时器再调用,就避免了重复调用定时器,避免了速度加快
obj.timer = setInterval(function () {
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
clearInterval(obj.timer); //当盒子的left值大于400后就停止计时器
//回调函数写到停止计时器的位置
if (callback()) {
callback();
}
}
obj.style.left = obj.offsetLeft + step + 'px'; //在原先的位置加上步长直
}, 15)
}
二、移动端的特效
1、触屏事件touch:
- touchstart 手指触摸到一个DOM元素时触发
- touchmove 手指在一个DOM元素上滑动时触发
- touchend 手指从一个DOM元素上移开时触发
触摸事件对象 TouchEvent
原理:是一类描述手指触摸平板的状态变化的事件,这类事件用于描述一个或多个触点,使开发者可以检测触点的移动,触点的增加和减少
- touches 正在触摸屏幕的所有手指的一个列表
里面有长度就是有几根手指 排序从0开始如果它们侦听的是DOM元素则和targetTouches是一样的
- targetTouches 正在触摸当前DOM元素上的手指的一个列表
e.targetTouches[0]
获得第一个手指的相关信息 比如 手指的坐标等...
- changedTouches 手指状态发生了改变的列表,从无到有,从有到无变化
与上面不同的是当手指离开屏幕的时候就没有 touches、targetTouches,但是会有chagedTouches
2、移动端的拖动元素:【touchstart、touchmove、touchend 可以实现拖动元素】
拖动元素需要当前手指的坐标值 我们可以使用targetTouches[0] 里面的pageX和pageY
原理:用盒子原来的位置 + 手指移动的距离
手指移动的距离:手指滑动中的位置 - 手指刚开始触摸的位置
拖动元素三部曲:
- touchstart:获得手指初识位置,同时获得盒子原来的位置
- touchmove:计算手指的滑动距离,并且移动盒子
- 离开手指touchend:
<body>
<div></div>
<script>
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>
3、click延时解决方案
移动端click事件会300ms的延时,原因是移动端屏幕双击会缩放页面
三种解决方案:
- 禁止用户缩放
<meta name ="viewport" content="user-scalable=no">
- 利用touch事件自己封装这个事件解决300ms延迟
原理:
- 当我们手指触摸屏幕,记录 当前触摸时间
- 当我们手指离开屏幕,用离开的时间减去触摸的时间
- 如果时间小于150ms,并且没有滑动过屏幕,那么我们就定义为点击
- fastclick插件
引入文件:<script src="./js/fastclick.js"></script>
使用:在你script里面添加此代码
<script>
// 使用此插件
if ('addEventListener' in document) {
document.addEventListener('DOMContentLoaded', function () {
FastClick.attach(document.body);
}, false);
}</script>
三、本地存储
特征:
- 数据存储在用户浏览器中
- 设置、读取方便、甚至页面刷新不丢失数据
- 容量较大
- 只能存储字符串,可以将对象json.stringify()编码后存储
方法一:window.sessionStorage
特征:
- 生命周期为关闭浏览器窗口
- 在同一个窗口(页面)下数据可以共享
- 以键值对的形式存储使用
存储数据 | 存储数据: sessionStorage.setItem(key,value); |
获取数据 | sessionStorage.getltem(key) |
删除数据 | sessionStorage.removeltem(key) |
删除所有数据 | sessionStorage.clear() |
方法二:window.localStorage
特征:
- 生命周期永久生效,除非手动删除 否则关闭页面也会存在
- 可以多窗口共享 同一浏览器可以共享
- 以键值对的形式存储使用
存储数据 | locaStorage.setltem(key,value) |
获取数据 | localStorage.getltem(key); |
删除数据 | localStotage.removeltem(key) |
删除所有数据 | localStorage.clear() |
<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>