网页特效,缓动动画函数封装

元素偏移量

  1. offsetTop/Left,动态的获取位置,具有定位的父元素的距离,如果没有则以body为准
  2. offsetWidth/Height可以获取元素的大小 包括padding,border
  3. offsetParent返回带有定位的父亲,否则是body,parentNode返回最近一级 的父亲

offset和style

  1. style只能得到行内样式表中的样式值,并且获取的属性值是有单位的
  2. 获取元素使用offset更合适,更改样式使用style

鼠标点击盒子后获取坐标

1
2
3
4
5
6
7
<script>
var box =document.querySelector('.box');
box.addEventListener('click',function(e){
var x = e.pageX - this.offsetLeft;
console.log(x);
})
</script>

client系列

  1. clientWidth返回自身的宽度不包含边框,包含padding

立即执行函数

  1. 立即执行函数(function() {})() 或者(function(){}()),
  2. (function() {})() 第二个小括号可以看作调用函数
  3. (function(){}()), 多个立即执行函数要加;
  4. 创建一个独立作用域,避免了命名冲突

放大镜效果

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
<style>
.box {
position: relative;
margin-top: 200px;
margin-left: 100px;
top: 0;
left: 0;
width: 400px;
height: 400px;
background-color: rgb(163, 155, 155);
border-radius: 10px;
cursor: move;
}

.box .imgs {
position: absolute;
top: 0;
left: 0;
width: 64%;
margin-left: 74px;
margin-top: 3px;
vertical-align: middle;
}

.mask {
display: none;
position: absolute;
top: 0;
left: 0;
width: 100px;
height: 100px;
border-radius: .625rem;
background-color: rgb(80, 29, 45);
opacity: .5;
}

.big {
display: none;
position: relative;
width: 600px;
height: 600px;
top: 0;
left: 410px;
border-radius: .625rem;
overflow: hidden;
}

.big .imgc {
position: absolute;
top: 0;
left: 0;
width: 300px;
margin-left: 100px;
}
</style>

<body>
<div class="box">
<img class="imgs" src="https://cdn.jsdelivr.net/gh/Rr210/hexofixed@1.07.01/img/api/phone/2ae5b713777378e1.jpg"
alt="">
<div class="mask"></div>
<div class="big"><img class="imgc"
src="https://cdn.jsdelivr.net/gh/Rr210/hexofixed@1.07.01/img/api/phone/2ae5b713777378e1.jpg" alt="">
</div>
</div>
<script>
var box = document.querySelector('.box');
var img = box.querySelector('.imgs');
var mask = box.querySelector('.mask');
var big = box.querySelector('.big');
var imgc = big.querySelector('.imgc');
box.addEventListener('mouseover', function () {
mask.style.display = 'block';
big.style.display = 'block';
})
box.addEventListener('mouseout', function () {
mask.style.display = 'none';
big.style.display = 'none';
})
box.addEventListener('mousemove', function (e) {
x = e.pageX - box.offsetLeft;
y = e.pageY - box.offsetTop;
maxX = x - mask.offsetWidth / 2;
maxY = y - mask.offsetHeight / 2;
var maxx = box.offsetWidth - mask.offsetWidth;
if (maxX <= 0) {
maxX = 0;
} else if (maxY <= 0) {
maxY = 0;
} else if (maxX >= maxx) {
maxX = maxx;
} else if (maxY >= maxx) {
maxY = maxx;
}
mask.style.left = maxX + 'px';
mask.style.top = maxY + 'px';
var bigmaxx = big.offsetWidth - imgc.offsetWidth;
var bigmaxy = big.offsetHeight - imgc.offsetHeight;
imgbx = maxX * bigmaxx / maxx;
imgby = maxY * bigmaxy / maxx;
imgc.style.left = -imgbx + 'px';
imgc.style.top = -imgby + 'px';
})

</script>

查看样式图例

scroll系列属性

  1. scrollTop/scrollLeft/ScrollWidth/scrollHeight
  2. overflow:auto 使滑动自动显示
  3. 页面被卷去的头部:可以通过window.pageYOffset获得如果是被卷的是左window.pageXoffset
  4. 注意,元素被卷去的头部是elent.scollTop ,如果是页面被卷去的头部则是window.pageYoffset

查看实例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
<body>
<style>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}

.box1 {
width: 400px;
height: 200px;
background-color: rgb(37, 150, 47);
margin: 10px auto;

}

.box2 {
width: 400px;
height: 400px;
background-color: rgb(37, 127, 150);
margin: 10px auto;
}

.box3 {
width: 400px;
height: 1000px;
background-color: rgb(141, 37, 150);
margin: 10px auto;
}

.aside {
position: absolute;
width: 50px;
height: 150px;
background-color: rgb(141, 133, 26);
top: 300px;
right: calc(50% - 250px);
padding: 10px;
padding-top: 30px;
text-align: center;
border-radius: 10px;
}
.aside span{
display: none;
cursor: pointer;
}
</style>
<div class="aside"><span>返回顶部</span></div>
<div class="box1">盒子一</div>
<div class="box2">盒子二</div>
<div class="box3">盒子三</div>

<script>
var box1 = document.querySelector('.box1');
var box2 = document.querySelector('.box2');
var box3 = document.querySelector('.box3');
var asidese = document.querySelector('.aside');
var bon = asidese.offsetTop - box2.offsetTop
document.addEventListener('scroll', function () {
console.log(box2.offsetTop);
console.log('aside的距离'+asidese.offsetTop);
if (pageYOffset >= box2.offsetTop) {
asidese.style.position = 'fixed';
asidese.style.top = bon + 'px'
}
else{
asidese.style.position = 'absolute';
asidese.style.top = '300px'
}
if (pageYOffset >= box3.offsetTop) {
asidese.children[0].style.display = 'block';
}else{
asidese.children[0].style.display = 'none';
}
})
console.log("box3的值"+box3.offsetTop);
var btn = asidese.children[0];
console.log(asidese.children[0]);
btn.addEventListener('click',function(){
document.body.scrollTop = document.documentElement.scrollTop = 0;
})
</script>

查看图例

三大系列的对比

  1. offsetWidth 返回自身,并且包括padding,border,不带单位,经常用于获取元素的位置
  2. clientWidth返回自身,但是不包括border,包括padding,经常用于获取元素的大小
  3. scrollWidth 返回自身实际的宽度,元素的内容,但是不含边框返回数值不带单位 经常用于获取滚动的距离,注意页面滚动 通过window.pageXoffset获得,元素滚动距离通过scrollTop或者scrollLeft获取

mouseover和mouseenter的区别

  1. mouseover:鼠标经过自身盒子触发,子盒子也会触发
  2. mouseenter:鼠标经过自身盒子才会触发,不会进行冒泡处理

动画函数的封装

  1. 动画原理:使用定时器+元素定位+元素offset
  2. 给不同元素指定不同的定时器
  3. 缓动动画的原理:使用动画缓动执行,使速度慢慢停下来(目标值-现在的位置)
  4. 缓动动画需要将步长值改为整数,使用Math.ceil函数 向上取整
  5. 缓动动画也可以添加回调函数

缓动匀速封装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
<style>
* {
padding: 0;
margin: 0;
}

.box {
position: absolute;
left: 0;
width: 100px;
height: 100px;
margin: 100px;
background-color: rgb(6, 143, 153);
}
span{
position: absolute;
left: 0;
width: 100px;
height: 100px;
margin: 210px;
margin-left: 100px;
background-color: rgb(21, 8, 139);
}
</style>

<div class="box"></div>
<span></span>
<script>
var box = document.querySelector('.box');
var span =document.querySelector('span')
function animate(obj, target) {
clearInterval(obj.timer)
obj.timer = setInterval(function () {
if (obj.offsetLeft >= target) {
clearInterval(timer)
}
obj.style.left = obj.offsetLeft + 1 + 'px';
}, 150)
}
var box1= animate(box, 800);
var span1 = animate(span,900)
</script>

缓动变速封装

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
<style>
* {
padding: 0;
margin: 0;
box-sizing: border-box;
}

.box {
position: absolute;
display: block;
left: 0;
width: 100px;
height: 100px;
margin: 100px 0;
background-color: rgb(6, 143, 153);
}

span {
position: absolute;
left: 0;
width: 100px;
height: 100px;
margin: 200px 0;
background-color: rgb(21, 8, 139);
}
</style>

<div class="box"></div>
<span></span>
<script>
var box = document.querySelector('.box');
var span = document.querySelector('span');

function animate(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);
if (callback) {
callback();
}
}
obj.style.left = obj.offsetLeft + step + 'px';
}, 15)
}
var box1 = animate(box, 800, function () {
box.style.display = 'none'
});
var span1 = animate(span, 900)
</script>

缓动函数封装地址

函数地址

利用缓动函数做一个鼠标触碰后移动的案例

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
<!DOCTYPE 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>
<style>
* {
margin: 0;
padding: 0;
}

body {
width: 100%;
width: 100%;
overflow-x: hidden;
}
.container,.box,.box2{
border-radius: 10px 0 0 10px;
}
.container {
position: absolute;
right: 0px;
bottom: 50px;
width: 50px;
height: 50px;
background-color: rgb(83, 3, 3);
}

.box {
position: absolute;
width: 50px;
height: 50px;
right: 0;
bottom: 0px;
font-size: 20px;
font-weight: 600;
color: #fff;
text-align: center;
line-height: 50px;
background-color: rgb(42, 23, 94);
}

.box2 {
position: absolute;
right: -150px;
bottom: 0;
width: 150px;
height: 50px;
font-size: 20px;
font-weight: 600;
color: #fff;
text-align: center;
line-height: 50px;
background-color: rgb(42, 23, 94);
}
</style>
<div class="container">
<div class="box">&lt;</div>
<div class="box2">你好世界</div>
</div>
<script>
var container = document.querySelector('.container');
var box2 = document.querySelector('.box2');
var box = document.querySelector('.box');
container.addEventListener('mouseover', function () {
animate(box2, -140, 15);
box.innerHTML = '&gt;';
})
container.addEventListener('mouseout', function () {
animate(box2, 140, 15);
box.innerHTML = '&lt;'
})
</script>
<script src="https://cdn.jsdelivr.net/gh/Rr210/image@master/hexo/4/animate.js"></script>

</body>

</html>

查看样式

缓动函数 - 匀速运动

  1. 在匀速运动的过程中设置每次移动的距离如果大于1px,会使最后的目标位置变大,并且在封装过程中,if判断必须设置为>=,看一下样式效果
  2. 看控制台console(obj.offsetLeft)的值可以看出在设置匀速运动时,如果每次移动的距离大于1px,最后得到的距离左侧的位置大于目标位置,再做判断时要设置为对象距离左侧的位置>=目标位置

查看答案

  • 缓动动画函数 封装 【地址

代码展示

查看答案

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
// 封装一个匀速或者变速的缓动文件
// 第一是减速的
function animate(obj, target, speed,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);
if (callback) {
callback();
}
}
obj.style.left = obj.offsetLeft + step + 'px';
}, speed)
}
// 第二个封装匀速
// 对象,目标位置,每次移动的距离,移动速度,回调函数
// var demo = animateun(obj, target, csteps, callback)
function animateun(obj, target,csteps,speed,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);
if (callback) {
callback();
}
}
obj.style.left = obj.offsetLeft + csteps + 'px';
}, speed)
}

以上内容是我在实际操作过程中出现的问题