PC端网页特效
1. 元素偏移量offset系列
- offset
offset 翻译过来就是偏移量,我们是哦那个offset系列相关属性可以动态得到该元素(偏移),大小等。
offset属性 | 说明 |
---|---|
element.offsetTop | 返回元素相对带有定位父元素上方的偏移 |
element.offsetLeft | 返回元素相对带有定位父元素左边框的偏移 |
element.offsetParent | 返回元素相对带有定位父元素,如果父级都没有定位则返回body |
element.offsetWidth | 返回自身包括padding、边框、内容区的宽度,返回数值不带单位 |
element.offsetHeight | 返回自身包括padding、边框、内容区的高度,返回数值不带单位 |
- offset与style区别
offset:
- offset可以得到任意样式表中的样式值
- offset一列获得的数值是没有单位的
- offsetWidth包含padding+border+width
- offsetWidth等属性是只读属性,只能获取不能赋值
- 获取元素大小位置,用offset更合适
style:
- style可以得到行内样式值
- style一列获得的数值是带有单位的
- style.width获得不包含padding和border的值
- style.width是可读写属性,可以获取也可以赋值
- 所以,我们想要给元素更改值,则需要用style改变
案例1: 获取鼠标在盒子内的坐标案例
<style>
.box {
width: 200px;
height: 300px;
background-color: pink;
margin-top: 50px;
margin-left: 100px;
}
</style>
<div class="box"></div>
<script>
var box = document.querySelector('.box');
box.addEventListener('click', function(e){
var x = e.pageX - this.offsetLeft;
var y = e.pageY - this.offsetTop;
this.innerHTML = 'x坐标是' + x + 'y坐标是' + y;
})
</script>
案例二:模态框拖拽
点击登录显示登录框,点击关闭,登录框隐藏,鼠标按下移动登录框
案例分析:
(1)获取元素
(2)点击弹出层这个链接 link,让模态框背景mask 和模态框login 显示出来
(3)点击 span,隐藏 模态框背景mask 和 模态框login
(4)开始拖拽,当鼠标在模态框中的title区域按下,获得鼠标在盒子内的坐标;鼠标移动的时候,把鼠标在页面中的坐标,减去 鼠标在盒子内的坐标就是模态框的left和top的值;当鼠标在浏览器中任意地方弹起的时候(所以依然用document绑定事件),移除之前绑定的鼠标移动(mousemove)的事件(move)
<style>
.login-header {
width: 100%;
text-align: center;
height: 30px;
font-size: 24px;
line-height: 30px;
}
ul,
li,
ol,
dl,
dt,
dd,
div,
p,
span,
h1,
h2,
h3,
h4,
h5,
h6,
a {
padding: 0px;
margin: 0px;
}
.login {
display: none;
/*先给模态框设置隐藏*/
position: fixed;
/*给模态框加一个固定定位*/
left: 50%;
top: 50%;
transform: translate(-50%, -50%);
/*以上三句话加上定位,实现login模态框在浏览器中水平垂直居中*/
background: #ffffff;
box-shadow: 0px 0px 20px #ddd;
z-index: 9999;
border: #ebebeb solid 1px;
width: 512px;
height: 280px;
}
.login-title {
width: 100%;
margin: 10px 0px 0px 0px;
text-align: center;
line-height: 40px;
height: 40px;
font-size: 18px;
position: relative;
cursor: move;
}
.login-input-content {
margin-top: 20px;
}
.login-button {
display: none;
/*献给模态框设置隐藏*/
width: 100%;
height: 100%;
position: fixed;
top: 0px;
left: 0px;
background: rgba(0, 0, 0, .3);
}
a {
text-decoration: none;
color: #000000;
}
.login-button a {
display: block;
}
.login-input input.list-input {
float: left;
line-height: 35px;
height: 35px;
width: 350px;
border: 1px solid #ebebeb;
text-indent: 5px;
}
.login-input {
overflow: hidden;
margin: 0px 0px 20px 0px;
}
.login-input label {
float: left;
width: 90px;
padding-right: 10px;
text-align: right;
line-height: 35px;
height: 35px;
font-size: 14px;
}
.login-title span {
position: absolute;
font-size: 12px;
right: -20px;
top: -30px;
background: #ffffff;
border: 1px solid #ebebeb;
width: 40px;
height: 40px;
border-radius: 20px;
cursor: pointer;
}
</style>
<div class="login-header"><a id="link" href="javascript:;">点击,弹出登录框</a></div>
<div id="login" class="login">
<div id="title" class="login-title">登陆会员
<span><a id="closeBtn" href="javascript:void(0);" class="close-login">关闭</a></span>
</div>
<div class="login-input-content">
<div class="login-input">
<label>用户名:</label>
<input type="text" placeholder="请输入用户名" name="info[username]" id="username" class="list-input">
</div>
<div class="login-input">
<label>登陆密码:</label>
<input type="password" placeholder="请输入登陆密码" name="info[password]" id="password" class="list-input">
</div>
</div>
<div id="loginBtn" class="login-button"><a href="javascript:void(0);" id="login-button-submit">会员登录</a></div>
</div>
<div id="bg" class="login-bg"></div>
<script>
//1.获取元素
var login = document.querySelector('.login');
var mask = document.querySelector('.login-bg');
var link = document.querySelector('#link');
var title = document.querySelector('#title');
var span = document.querySelector('span');
//2. 点击弹出层这个链接 link,让模态框背景mask 和模态框login 显示出来
link.addEventListener('click', function(){
mask.style.display = 'block';
login.style.display = 'block';
})
//3. 点击 span,隐藏 模态框背景mask 和 模态框login
span.addEventListener('click', function(){
mask.style.display = 'none';
login.style.display = 'none';
e.stopPropagation();
//解决了添加鼠标按下事件(mousedown)后,由于默认是冒泡,会导致点击login模态框的子集span也可以移动模态框的BUG
})
//4. 开始拖拽
//(1) 当鼠标在模态框中的title区域按下,获得鼠标在盒子内的坐标
title.addEventListener('mousedown', function(e){
//(2) 鼠标移动的时候,把鼠标在页面中的坐标,减去 鼠标在盒子内的坐标就是模态框的left和top的值
var x = e.pageX - login.offsetLeft;
var y = e.pageY - login.offsetTop;
document.addEventListener('mousemove', move);
//只有按下后才能拖动鼠标(mousemove),所以mousemove要写在mousedown里面
//在页面中任意地方都可以移动鼠标,所以用document绑定事件
function move(e){
login.style.left = e.pageX - x + 'px';
login.style.top = e.pageY - y + 'px';
//注意:e.pageX, e.pageY, e.offsetLeft, e.offsetTop返回的值都没有单位,所以要用拼接字符串加上单位
}
//(3) 当鼠标在浏览器中任意地方弹起的时候(所以依然用document绑定事件),移除之前绑定的鼠标移动(mousemove)的事件(move)
document.addEventListener('mouseup', function(){
document.removeEventListener('mousemove', move);
})
})
</script>
2. 元素可视区client系列
client翻译过来就是客户端,我们是哦那个client系列的相关来获取元素的可视区的相关信息
通过client系列的相关属性可以动态的得到该元素的边框大小,元素大小
client系列属性 | 说明 |
---|---|
element.clientTop | 返回元素上边框的大小 |
element.clientLeft | 返回元素左边框的大小 |
element.clientWidth | 返回自身包括padding内容区的宽度,不包含边框,返回的数值不带单位 |
element.clientHeight | 返回自身包括padding内容区的高度,不包含边框,返回的数值不带单位 |
立即执行函数:
不需要调用,立马能够自己执行的函数
(function(){})()或者
(function(){}());
例:
(function(){
console.log(2)
})() //第二个小括号可以看作是调用函数,也可以传递参数进来
(function(a, b){
console.log(a + b)
}(1, 2));//3
多个立即执行函数之间用’;‘隔开
立即执行函数最大的作用就是:独立创建了一个作用域
3. 元素滚动scroll系列
scroll系列属性 | 说明 |
---|---|
element.scrollTop | 返回被卷去的上侧距离,返回数值不带单位 |
element.scrollLeft | 返回被卷去的左侧距离,返回数值不带单位 |
element.scrollWidth | 返回自身实际宽度,不含边框,返回数值不带单位 |
element.scrollHeight | 返回自身实际高度,不含边框,返回数值不带单位 |
页面被卷曲的头部:可以通过window.pageYOffset获得
如果被卷去是左侧,则window.pageXOffset获得
声明了DTD,使用document.documentElement.scrollTop
未声明DTD,使用document.body.scrollTop
案例:仿淘宝固定右侧侧边栏
<style>
.slider-bar {
position: absolute;
left: 50%;
top: 300px;
margin-left: 600px;
width: 45px;
height: 130px;
background-color: pink;
}
.w {
width: 1200px;
margin: 10px auto;
}
.header {
height: 150px;
background-color: purple;
}
.banner {
height: 250px;
background-color: skyblue;
}
.main {
height: 1000px;
background-color: yellowgreen;
}
span {
display: none;
position: absolute;
bottom: 0;
}
</style>
<div class="slider-bar">
<span class="goBack">返回顶部</span>
</div>
<div class="header w">头部区域</div>
<div class="banner w">banner区域</div>
<div class="main w">主体部分</div>
<script>
//1.获取元素
var sliderbar = document.querySelector('.slider-bar');
var banner = document.querySelector('.banner');
//banner.offsetTop 就是被卷去头部的大小 一定要写到滚动的外面
var bannerTop = banner.offsetTop;
//当我们侧边栏固定定位之后应该变化的数值
var sliderbarTop = sliderbar.offsetTop - bannerTop;
//获取main元素
var main = document.querySelector('.main');
var goBack = document.querySelector('.goBack');
var mainTop = main.offsetTop;
//2. 页面滚动事件 scroll
document.addEventListener('scroll', function(){
//window.pageYOffset 页面被卷去的头部
console.log(window.pageYOffset);
//3. 当我们页面被卷去的头部大于等于170 此时 侧边栏就要改为固定定位
if(window.pageYOffset >= bannerTop){
sliderbar.style.position = 'fixed';
sliderbar.style.top = sliderbarTop + 'px';
}else {
sliderbar.style.position = 'absolute';
}
//4. 当我们页面滚动到main盒子,就是显示 goback 模块
if(window.pageYOffset >= mainTop){
goBack.style.display = 'block';
}else {
goBack.style.display = 'none';
}
})
</script>
4. mouseenter 和 mouseover 事件区别
(1)mouseover鼠标经过自身盒子会触发,经过子盒子还会触发
(2)mouseenter只会经过自身盒子触发
5. 动画函数封装
- 动画原理实现
核心原理:通过定时器setInterval()不断移动盒子位置
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<style>
div {
position: absolute;
left: 0;
width: 100px;
height: 100px;
background-color: pink;
}
</style>
</head>
<body>
<div></div>
<script>
// 动画原理
// 1. 获得盒子当前位置
// 2. 让盒子在当前位置加上1个移动距离
// 3. 利用定时器不断重复这个操作
// 4. 加一个结束定时器的条件
// 5. 注意此元素需要添加定位, 才能使用element.style.left
var div = document.querySelector('div');
var timer = setInterval(function() {
if (div.offsetLeft >= 400) {
// 停止动画 本质是停止定时器
clearInterval(timer);
}
div.style.left = div.offsetLeft + 1 + 'px';
}, 30);
</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>
<style>
div {
position: absolute;
left: 0;
width: 100px;
height: 100px;
background-color: pink;
}
span {
position: absolute;
left: 0;
top: 200px;
display: block;
width: 150px;
height: 150px;
background-color: purple;
}
</style>
</head>
<body>
<button>点击夏雨荷才走</button>
<div></div>
<span>夏雨荷</span>
<script>
//简单动画函数封装obj目标对象 target 目标位置
//给不同的元素指定了不同的定时器
function animate(obj, target) {
//当我们不断地点击按钮,这个元素的速度会越来越快,因为开启了太多的定时器
//解决方案就是 让我们元素只有一个定时器执行
//先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function(){
if (obj.offsetLeft >= target) {
//停止动画 本质是停止定时器
clearInterval(obj.timer);
}
obj.style.left = obj.offsetLeft + 1 + 'px';
}, 30);
}
var div = document.querySelector('div');
var span = document.querySelector('span');
var btn = document.querySelector('button');
//调用函数
animate(div, 300);
//animate(span, 200);
btn.addEventListener('click', function(){
animate(span, 200);
})
</script>
</body>
</html>
- animate.js
function animate(obj, target, callback) {
//先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function(){
//步长值写到定时器里面
//我们把步长值改为整数 不要出现小数的问题
var step = Math.ceil((target - obj.offsetLeft) / 10);
//var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
//停止动画 本质是停止定时器
clearInterval(obj.timer);
//回调函数写到定时器结束里面
if(callback){
//调用函数
callback();
}
}
obj.style.left = obj.offsetLeft + step + 'px';
}, 15);
}
- 缓动效果
<!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;
left: 0;
width: 100px;
height: 100px;
background-color: pink;
}
span {
position: absolute;
left: 0;
top: 200px;
display: block;
width: 150px;
height: 150px;
background-color: purple;
}
</style>
</head>
<body>
<button class="btn500">点击夏雨荷到500</button>
<button class="btn800">点击夏雨荷到800</button>
<span>夏雨荷</span>
<script>
//简单动画函数封装obj目标对象 target 目标位置
//给不同的元素指定了不同的定时器
function animate(obj, target, callback) {
//先清除以前的定时器,只保留当前的一个定时器执行
clearInterval(obj.timer);
obj.timer = setInterval(function(){
//步长值写到定时器里面
//我们把步长值改为整数 不要出现小数的问题
//var step = Math.ceil((target - obj.offsetLeft) / 10);
var step = (target - obj.offsetLeft) / 10;
step = step > 0 ? Math.ceil(step) : Math.floor(step);
if (obj.offsetLeft == target) {
//停止动画 本质是停止定时器
clearInterval(obj.timer);
//回调函数写到定时器结束里面
if(callback){
//调用函数
callback();
}
}
obj.style.left = obj.offsetLeft + step + 'px';
}, 30);
}
//var div = document.querySelector('div');
var span = document.querySelector('span');
var btn500 = document.querySelector('.btn500');
var btn800 = document.querySelector('.btn800');
//调用函数
//animate(div, 300);
//animate(span, 200);
btn500.addEventListener('click', function(){
animate(span, 500);
})
btn800.addEventListener('click', function(){
//调用函数
animate(span, 800, function(){
//alert('你好吗');
span.style.backgroundColor = 'red';
});
})
//匀速动画 就是 盒子是当前的位置 + 固定的值 10
//缓动动画就是 盒子当前的位置 + 变化的值((目标值-现在的位置)/ 10)
</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>
<style>
.sliderbar {
position: fixed;
right: 0;
/*设置动画一定要有定位*/
bottom: 100px;
width: 40px;
height: 40px;
text-align: center;
line-height: 40px;
cursor: pointer;
color: #fff;
}
.con {
position: absolute;
left: 0;
top: 0;
width: 200px;
height: 40px;
background-color: purple;
z-index: 1;
}
</style>
<script src="animate.js"></script>
</head>
<body>
<div class="sliderbar">
<span>←</span>
<div class="con">问题反馈</div>
</div>
<script>
//1.获取元素
var sliderbar = document.querySelector('.sliderbar');
var con = document.querySelector('.con');
//当我们鼠标经过 sliderbar 就会让 con 这个盒子滑动到左侧
//当我们鼠标离开 sliderbar 就会让 con 这个盒子滑动到右侧
sliderbar.addEventListener('mouseenter', function(){
//animate(obj,target,callback);
animate(con, -160, function(){
//当我们动画执行完毕 就把 <-- 改为 -->
sliderbar.children[0].innerHTML = '→';
});
})
sliderbar.addEventListener('mouseleave', function(){
//animate(obj,target,callback);
animate(con, 0,function(){
sliderbar.children[0].innerHTML = '←';
});
})
</script>
</body>
</html>
6. 节流阀
目的:当上一个函数动画内容执行完毕,再去执行下一个函数动画,让时间无法连续触发。
核心思路:利用回调函数,添加一个变量来控制,锁住函数和解锁函数。
//开始设置一个变量
var flag = true;
if(flag){
flag = false;
do something;
}
//关闭水龙头,利用回调函数,动画执行完毕
flag = true //打开水龙头