学习视频以及笔记参考来源:
JavaScript基础语法-dom-bom-js-es6新语法-jQuery-数据可视化echarts黑马pink老师前端入门基础视频教程(500多集)持续_哔哩哔哩_bilibili
一、元素偏移量 offset 系列
1、offset 常用属性
offset 翻译过来就是偏移量,我们使用 offset 系列相关属性可以动态的得到该元素的位置(偏移)、大小等。
注意点:
(1)获取元素距离带有定位父元素的位置,也就是说,得到的是相对于有定位的父元素的偏移,如果没有父级或者父级都没有定位,则返回body。
(2)返回的是数值,不带单位。
2、offset 与 style 的区别
3、案例
3.1 模态框拖拽
效果:按住鼠标可以拖拽模态框移动,鼠标松开,停止模态框移动。
<body>
<div></div>
<script>
// 1. 获取事件
var div = document.querySelector('div');
// 2. 当鼠标按下时,获取盒子的 offset = 鼠标相对于页面的距离 - 盒子相对于页面的距离
div.addEventListener('mousedown', function (e) {
// 获取鼠标点击位置相对于盒子的 offset
var x_offset = e.pageX - div.offsetLeft;
var y_offset = e.pageY - div.offsetTop;
// 定义一个鼠标移动事件
document.addEventListener('mousemove', move);
function move(e) {
// 固定鼠标相对于盒子的距离,动态计算盒子相对于页面的距离并将值赋值为盒子
var x_box = e.pageX - x_offset;
var y_box = e.pageY - y_offset;
div.style.marginLeft = x_box + 'px';
div.style.marginTop = y_box + 'px';
}
// 当鼠标弹起时,删除鼠标移动事件
document.addEventListener('mouseup', function () {
document.removeEventListener('mousemove', move);
})
})
</script>
</body>
3.2 仿京东放大镜
效果:仿造京东物品详情页放大展示效果。
案例展示效果:图片是随便找的图 and 鼠标截图的时候显示不出来,大概是这样。
三个模块:
(1)鼠标经过小图片盒子,黄色的遮挡层和大图片盒子显示,离开隐藏这两个盒子。
(2)黄色的遮挡层跟随鼠标功能,并且黄色遮挡层不会超过小图片盒子。
(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>
* {
margin: 0;
padding: 0;
}
.small {
position: relative;
width: 300px;
height: 200px;
margin: 200px 300px;
cursor: move;
}
.small img {
width: 100%;
height: 100%;
}
.mask {
display: none;
position: absolute;
top: 0;
left: 0;
width: 150px;
height: 150px;
background-color: antiquewhite;
/* 设置透明度 */
opacity: .5;
}
.big {
display: none;
position: absolute;
top: 0;
left: 310px;
height: 450px;
width: 450px;
overflow: hidden;
border: 1px solid #ccc;
}
.big img {
position: absolute;
top: 0;
left: 0;
width: 900px;
height: 600px;
}
</style>
</head>
<body>
<div class="small">
<img src="images/desktop_6.jpg" alt="">
<!-- 遮挡层 -->
<div class="mask"></div>
<!-- 放大后的图片 -->
<div class="big">
<img src="images/desktop_6.jpg" alt="">
</div>
</div>
<script>
var small = document.querySelector('.small');
var mask = document.querySelector('.mask');
var big = document.querySelector('.big');
var big_img = big.querySelector('img');
console.log(big_img);
small.addEventListener('mousemove', function (e) {
mask.style.display = 'block';
big.style.display = 'block';
// 1. 实现遮挡层可以跟随鼠标移动
// 1.1 获取鼠标相对于 small 盒子的 offset,并将值赋值给 mask
var x_mask_small = e.pageX - small.offsetLeft - mask.offsetWidth / 2;
var y_mask_small = e.pageY - small.offsetTop - mask.offsetHeight / 2;
// 1.2 保证 mask 不会超出图片,要加上一些限制条件
if (x_mask_small <= 0) {
x_mask_small = 0;
} else if (x_mask_small >= this.offsetWidth - mask.offsetWidth) {
x_mask_small = this.offsetWidth - mask.offsetWidth;
}
if (y_mask_small <= 0) {
y_mask_small = 0;
} else if (y_mask_small >= this.offsetHeight - mask.offsetHeight) {
y_mask_small = this.offsetHeight - mask.offsetHeight;
}
mask.style.left = x_mask_small + 'px';
mask.style.top = y_mask_small + 'px';
// 2. 实现大图的放大展示效果
// 2.1 我这里的 small 图和 big 图是等比例的,因此我直接将之前获取的偏移值*比例得到大图的偏移值
var x_big = x_mask_small * (big.offsetWidth / this.offsetWidth);
var y_big = y_mask_small * (big.offsetHeight / this.offsetHeight);
// 2.2 将获取的偏移值赋值给 big 图的定位参数 left / top (加了定位,不加定位不能用哈)
big_img.style.left = - x_big + 'px';
big_img.style.top = - y_big + 'px';
})
// 3. 实现放大效果的显示与隐藏
small.addEventListener('mouseout', function () {
mask.style.display = 'none';
big.style.display = 'none';
})
</script>
</body>
</html>
二、元素可视区 client 系列
client 翻译过来就是客户端,我们使用 client 系列的相关属性来获取元素可视区的相关信息。通过 client 系列的相关属性可以动态的得到该元素的边框大小、元素大小等。
三、元素滚动 scroll 系列
scroll 翻译过来就是滚动的,我们使用 scroll 系列的相关属性可以动态的得到该元素的大小、滚动距离等。
1、scroll 系列属性
2、页面被卷去的头部
如果浏览器的高(或宽)度不足以显示整个页面时,会自动出现滚动条。当滚动条向下滚动时,页面上面被隐藏 掉的高度,我们就称为页面被卷去的头部。滚动条在滚动时会触发 onscroll 事件。
- 页面被卷去的头部可以通过 window.pageYOffset 获得;如果是被卷去的左侧 window.pageXOffset。
-
元素被卷去的头部是 element.scrollTop , 如果是页面被卷去的头部 则是 window.pageYOffset。
四、offset / client / scroll 对比
区别:(1)offset 包括 padding 、边框等宽度,client 与 scroll 则不包含。
(2)如果内容超出盒子,scroll 可以获取滚动距离,而其他两个不行。
主要用法:
(1)offset系列经常用于获得元素位置:offsetLeft / offsetTop。
(2)client 经常用于获取元素大小:clientWidth / clientHeight。
(3)scroll 经常用于获取滚动距离:scrollTop / scrollLeft。
(4)注意页面滚动的距离通过 window.pageXOffset 获得。
五、动画函数封装
1、原理
核心原理:通过定时器 setInterval() 不断移动盒子位置。
实现步骤:(1)获取盒子当前位置。(2)在盒子当前位置的基础上加上步长。(3)利用定时器不断重复 2 的操作。(4)增加结束定时器的条件。
注意:此元素需要添加定位,才能使用 element.style.left 。
2、动画函数的简单封装
给函数传递2个参数:动画对象和目标位置。
// 动画对象:obj ; 目标位置:target ;
function animate(obj, target) {
// 步长 step
var step = 5;
// 利用定时器重复操作
obj.timer = setInterval(function () {
// 获取当前位置:obj.offsetLeft
if (obj.offsetLeft > target) {
clearInterval(obj.timer);
} else {
// 可以通过修改步长 step 实现不同速度的动画
obj.style.left = obj.offsetLeft + step + 'px';
}
}, 50)
}
// 调用函数
animate(div, 300);
3、给动画函数添加回调函数
// 动画对象:obj ; 目标位置:target ; 回调函数 callback
function animate(obj, target, callback) {
obj.timer = setInterval(function () {
if (obj.offsetLeft > target) {
clearInterval(obj.timer);
if (callback) {
// 调用回调函数
callback();
}
} else {
obj.style.left = obj.offsetLeft + 5 + 'px';
}
}, 50)
}
// 调用函数
animate(div, 300, function() {});
六、案例:网页轮播图
1、 效果
2、 功能需求
(1)鼠标经过轮播图模块,左右按钮显示,离开隐藏左右按钮。
(2)点击右侧按钮一次,图片往左播放一张,以此类推, 左侧按钮同理。
(3)图片播放的同时,下面小圆圈模块跟随一起变化。
(4)点击小圆圈,可以播放相应图片。
(5)鼠标不经过轮播图, 轮播图也会自动播放图片。
(6)鼠标经过,轮播图模块, 自动播放停止。
案例分析:
是 ppt 里面直接截取的,我自己写代码的时候可能有一些细节不同,名字取得也不一样,主要是可以参考一下思路,感觉写的还是比较清晰的。
3、 实现的代码
这部分的代码主要是参照视频的思路来写的,但是我没有视频中的CSS案例,所以自己先写了一个简单的CSS和HTML的界面,再进行JS的实现,具体 code 如下:
<!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>
* {
margin: 0;
padding: 0;
}
li {
list-style: none;
}
.box {
position: relative;
width: 1280px;
height: 720px;
margin: 200px auto;
border: 1px solid #ccc;
overflow: hidden;
}
.box .conpic {
position: absolute;
top: 0;
left: 0;
width: 500%;
}
.box .conpic li img {
float: left;
width: 1280px;
height: 720px;
}
.forward,
.backward {
display: none;
position: absolute;
width: 60px;
height: 80px;
top: 50%;
left: 0;
background-color: rgb(204, 204, 204, .8);
border-radius: 0 35px 35px 0;
text-align: center;
line-height: 80px;
font-size: 30px;
cursor: pointer;
z-index: 666;
}
.forward {
left: 1220px;
border-radius: 35px 0 0 35px;
}
.circle {
position: absolute;
top: 92%;
left: 600px;
}
.circle li {
float: left;
width: 20px;
height: 20px;
border-radius: 50%;
background-color: aliceblue;
margin: 6px;
}
.circle .cirselect {
/* background-color: bisque; */
background-color: red;
}
</style>
</head>
<body>
<!-- 搭建结构 -->
<div class="box">
<div class="forward">></div>
<div class="backward"><</div>
<ul class="conpic">
<li>
<img src="images/desktop_9.jpg" alt="">
</li>
<li>
<img src="images/desktop_7.jpg" alt="">
</li>
<li>
<img src="images/desktop_8.jpg" alt="">
</li>
</ul>
<ul class="circle">
</ul>
</div>
<script>
var box = document.querySelector('.box');
var ul_img = document.querySelector('.conpic');
var forward = document.querySelector('.forward');
var backward = document.querySelector('.backward');
var sigwidth = ul_img.children[0].children[0].offsetWidth;
// 1. 鼠标经过显示左右按钮
box.addEventListener('mouseover', function () {
forward.style.display = 'block';
backward.style.display = 'block';
// 当鼠标在图片上则停止自动播放
clearInterval(timer);
timer = null;
})
box.addEventListener('mouseout', function () {
forward.style.display = 'none';
backward.style.display = 'none';
// 当鼠标离开则继续自动播放
timer = setInterval(function () {
// 手动调用时间
forward.click();
}, 2000)
})
// 2. 动态生成小圆圈
var ul_circle = document.querySelector('.circle');
for (var i = 0; i < ul_img.children.length; i++) {
// 创建一个 li
var li = document.createElement('li');
// 将 li 插入到 ul 当中
ul_circle.appendChild(li);
ul_circle.children[0].className = 'cirselect';
// 给 ul_img 和 ul_circle 都增加 index 属性
ul_img.children[i].setAttribute('index', i);
ul_circle.children[i].setAttribute('index', i);
ul_circle.children[i].addEventListener('click', function () {
// 排他思想实现小圆圈的选中效果
for (var j = 0; j < ul_circle.children.length; j++) {
ul_circle.children[j].className = '';
}
this.className = 'cirselect';
// 实现小圆圈和图片的对齐 ( 点击小圆圈会出现对应的图片 )
var index = this.getAttribute('index');
num = index;
animate(ul_img, -sigwidth * index);
})
}
// 3.左右按钮添加点击事件
// 复制第一张图片放到最后一张
var img0 = ul_img.children[0].cloneNode(true);
ul_img.append(img0);
console.log(ul_img);
// 定义右按钮点击事件
var num = 0;
// 定义节流阀,防止连续点击图片过快
var flag = true;
forward.addEventListener('click', function () {
if (flag) {
flag = false;
if (num == ul_img.children.length - 1) {
num = 0;
// 让最后一张图片和第一张图片无缝衔接(快速跳转,没有动画)
ul_img.style.left = 0;
}
// 排他思想实现小圆圈的选中效果
num++;
animate(ul_img, -sigwidth * num, callback_flag());
for (var j = 0; j < ul_circle.children.length; j++) {
ul_circle.children[j].className = '';
}
var index_num = ul_img.children[num].getAttribute('index');
ul_circle.children[index_num].className = 'cirselect';
}
})
console.log(num);
// 定义左按钮点击事件
backward.addEventListener('click', function () {
if (flag) {
flag = false;
if (num == 0) {
num = ul_img.children.length - 1;
// 让最后一张图片和第一张图片无缝衔接(快速跳转,没有动画)
ul_img.style.left = -num * sigwidth + 'px';
}
num--;
animate(ul_img, -sigwidth * num, callback_flag());
for (var j = 0; j < ul_circle.children.length; j++) {
ul_circle.children[j].className = '';
}
var index_num = ul_img.children[num].getAttribute('index');
ul_circle.children[index_num].className = 'cirselect';
}
})
function animate(obj, target, callback) {
clearInterval(obj.timer);
obj.timer = setInterval(function () {
if (obj.offsetLeft > target) {
step = -10;
} else {
step = 10;
}
// console.log(obj.offsetLeft, target);
if (obj.offsetLeft - target == 0) {
clearInterval(obj.timer);
} else {
obj.style.left = obj.offsetLeft + step + 'px';
}
}, 3)
}
// 4. 自动播放轮播图
var timer = setInterval(function () {
// 手动调用时间
forward.click();
}, 2000)
// 节流阀
function callback_flag() {
flag = true;
}
</script>
</body>
</html>