从零开始学 Web 之 BOM(二)定时器
大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新......
- github:https://github.com/Daotin/Web
- 微信公众号:Web前端之巅
- 博客园:http://www.cnblogs.com/lvonve/
- CSDN:https://blog.csdn.net/lvonve/
在这里我会从 Web 前端零基础开始,一步步学习 Web 相关的知识点,期间也会分享一些好玩的项目。现在就让我们一起进入 Web 前端学习的冒险之旅吧!
一、定时器
BOM 中有两中方式设置定时器。
1、方式一
特点:定时器可以重复使用。
// 参数有两个:
// 第一个参数:定时器定时结束处理函数
// 第二个参数:定时事件,单位毫秒。
// 返回值:定时器id值
var timeId = window.setInterval(function() {
// ...
}, 1000); // 定时1s
// 清除定时器
// 参数只有一个:定时器的 id 值。
window.clearInterval(timeId);
1.1、案例:图片摇起来
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
div {
position: absolute;
}
</style>
</head>
<body>
<input type="button" value="摇起来" id="btn1">
<input type="button" value="停止" id="btn2">
<div id="dv">
<img src="images/Daotin.png" alt="">
</div>
<script src="common.js"></script>
<script>
var timeId = 0;
my$("btn1").onclick = function () {
timeId = setInterval(function () {
//让图片动起来可以使div动起来
var x = parseInt(Math.random() * 100) + 1; // 1-100随机数
var y = parseInt(Math.random() * 100) + 1;
my$("dv").style.left = x + "px";
my$("dv").style.top = y + "px";
}, 100);
};
my$("btn2").onclick = function () {
clearInterval(timeId);
};
</script>
</body>
</html>
点击”摇起来“按钮,图片每隔 100ms 动一次,点击停止按钮,图片停止移动。
遗留问题:
多次点击“摇起来”按钮的时候,图片动的越来越快,而且点击“停止”按钮没法停下来。
原因分析:
多次点击“摇起来”按钮的时候,timeId 的值会有多个,而停止的时候,只会清理最后一个值,其他的值对应的定时器没有清理。
解决方法:
在每次点击按钮的时候,先进行一次定时器的清理动作。clearInterval(timeId);
2、方式二
特点:定时器是一次性的。
setTimeout(); // 参数与返回值同 setInterval();
这个定时器只执行一次。虽然只执行一次,但是还是要清零,不然就一直占内存。
clearTimeOut(); // 参数为 setTimeout() 定时器的 id。
2.1、案例:协议禁用倒计时
<body>
<input type="button" value="请认真阅读协议(5)" id="btn" disabled>
<script src="common.js"></script>
<script>
var time = 5;
var timeId = setInterval(function () {
time--;
if (time >= 0) {
my$("btn").value = "请认真阅读协议(" + time + ")";
} else {
clearInterval(timeId);
my$("btn").value = "同意";
my$("btn").disabled = false;
}
}, 1000);
</script>
</body>
倒计时后才可以点击同意按钮。
2.2、案例:移动元素
目标:有两个按钮,点击第一个按钮,div 缓慢移动到 400px 位置,点击第二个按钮缓慢移动到 800px 位置,再点击第一个按钮缓慢移动到 400px 位置......
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
* {
margin: 0;
padding: 0;
}
input {
margin-top: 10px;
}
div {
position: absolute;
width: 200px;
height: 100px;
background-color: yellowgreen;
margin-top: 10px;
/*left: 20px;*/
}
</style>
</head>
<body>
<input type="button" value="移动400px" id="btn1">
<input type="button" value="移动800px" id="btn2">
<div id="dv"></div>
<script src="common.js"></script>
<script>
// 移动400px
my$("btn1").onclick = function () {
animation(my$("dv"), 400);
};
// 移动800px
my$("btn2").onclick = function () {
animation(my$("dv"), 800);
};
// 封装动画移动函数
function animation(element, target) {
// 判断当前的位置
var current = element.offsetLeft; // 不能使用 element.style.left
var onestep = 7;
var timeId = setInterval(function () {
current += current < target ? onestep : -onestep;
if (Math.abs(current - target) >= onestep) {
element.style.left = current + "px";
} else {
clearInterval(timeId);
element.style.left = target + "px";
}
}, 20);
}
</script>
</body>
</html>
1、既然要缓慢移动,就需要定时器。
2、当前位置的获取不能使用 element.style.left; 而需要使用 element.offsetLeft; 因为所有写在标签中的 style 属性值都拿不到,只有内联的 style 属性值可以使用 element.style.left 拿到。而 element.offsetLeft 则两种方式都可以拿到。
3、需要每次移动的步数 onestep,而且有回退的需要,所以 onestep 可能是负数。
4、每次移动后判断现在的位置到目标位置的距离,如果大于 onestep,那么就移动 当前 current 加减 onestep 的位置,否则就移动到目标位置,这样做的目的是避免 onestep 的不确定,导致最后的终点与目标还差少许的距离。
5、使用当前与目标距离的绝对值来决定是前进还是后退。
6、到达目标位置后,关闭定时器。
7、将动画过程封装成一个函数,参数为移动的目标和移动的距离。
8、注意:div 需要脱离文档流。
2.3、案例:轮播图
2.3.1、简单的轮播图
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
* {
margin: 0;
padding: 0;
}
#box {
width: 400px;
height: 250px;
margin: 200px 0 0 400px;
position: relative;
border: 2px solid #31608a;
overflow: hidden;
}
ul {
width: 1300px;
position: absolute;
}
li {
list-style-type: none;
float: left;
}
img {
width: 400px;
height: 250px;
}
li a {
display: inline-block;
}
.sp {
position: absolute;
left: 50%;
margin-left: -45px;
bottom: 10px;
}
span {
float: left;
width: 20px;
height: 20px;
background-color: #fff;
border-radius: 10px;
text-align: center;
font: 400 16px/20px Consolas;
margin: 0 5px 0 5px;
cursor: pointer;
}
.current {
background-color: red;
color: #fff;
}
</style>
</head>
<body>
<div id="box">
<ul>
<li><a href="#"><img src="images/img1.jpg" alt=""></a></li>
<li><a href="#"><img src="images/img2.jpg" alt=""></a></li>
<li><a href="#"><img src="images/img3.jpg" alt=""></a></li>
</ul>
<div class="sp">
<span class="current">1</span>
<span>2</span>
<span>3</span>
</div>
</div>
<script src="common.js"></script>
<script>
// 获取box元素
var boxObj = my$("box");
// 获取ul元素,因为移动的就是整个ul
var ulObj = boxObj.children[0];
// 移动宽度
var moveWidth = document.getElementsByTagName("img")[0].offsetWidth;
// 获取所有span标签
var spanObjs = boxObj.children[1].getElementsByTagName("span");
// console.log(spanObjs);
for (var i = 0; i < spanObjs.length; i++) {
// 获取每个span的编号,设置自定义属性
spanObjs[i].setAttribute("index", "" + i);
spanObjs[i].onmouseover = function () {
for (var j = 0; j < spanObjs.length; j++) {
// 清空span背景
spanObjs[j].removeAttribute("class");
}
// 设置当前span标签
this.className = "current";
// 每个编号*移动的宽度就是移动到的目标位置
var index = this.getAttribute("index");
animation(ulObj, -index*moveWidth);
};
}
// 封装动画移动函数
function animation(element, target) {
// 判断当前的位置
var current = element.offsetLeft;
var onestep = 7;
var timeId = setInterval(function () {
current += current < target ? onestep : -onestep;
if (Math.abs(current - target) >= onestep) {
element.style.left = current + "px";
} else {
clearInterval(timeId);
element.style.left = target + "px";
}
}, 10);
}
</script>
</body>
</html>
1、移动的时候移动的是 ul,而不是单独的 li 或者 img。
2、span 小标签在鼠标进入的时候,背景变成红色。(排他事件:需要两步,第一清理所有,第二当前元素设置属性)
3、为每个 span 绑定事件时,程序开始,for 循环就运行完了,得不到每个span 标签的编号,所以要自定义属性保存每个 span 标签的编号。
4、直接调用封装好的动画移动函数来移动 ul 标签。
2.3.2、左右焦点轮播图
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<style>
* {
margin: 0;
padding: 0;
}
#box {
width: 400px;
height: 250px;
margin: 200px 0 0 400px;
position: relative;
border: 2px solid #31608a;
overflow: hidden;
}
ul {
width: 1300px;
position: absolute;
}
li {
list-style-type: none;
float: left;
}
img {
width: 400px;
height: 250px;
}
.sp {
width: 400px;
height: 50px;
position: absolute;
top: 100px;
display: none;
}
#left {
width: 50px;
height: 50px;
float: left;
cursor:pointer;
text-align:center;
font: 400 28px/50px Consolas;
background-color: #fff;
opacity: 0.4; /* 透明度 */
}
#right {
float: right;
width: 50px;
height: 50px;
cursor:pointer;
text-align:center;
font: 400 28px/50px Consolas;
background-color: #fff;
opacity: 0.4;
}
</style>
</head>
<body>
<div id="box">
<ul>
<li><a href="#"><img src="images/img1.jpg" alt=""></a></li>
<li><a href="#"><img src="images/img2.jpg" alt=""></a></li>
<li><a href="#"><img src="images/img3.jpg" alt=""></a></li>
</ul>
<div class="sp">
<span id="left"><</span>
<span id="right">></span>
</div>
</div>
<script src="common.js"></script>
<script>
// 获取box元素
var boxObj = my$("box");
// 获取ul元素,因为移动的就是整个ul
var ulObj = boxObj.children[0];
// 移动宽度
var moveWidth = document.getElementsByTagName("img")[0].offsetWidth;
// 获取sp标签
var spObj =boxObj.children[1];
// 获取span左标签
var leftObj = my$("left");
// 获取span右标签
var rightObj = my$("right");
var index = 0;
boxObj.onmouseover = function () {
spObj.style.display = "block";
};
boxObj.onmouseout = function () {
spObj.style.display = "none";
};
// 左移
leftObj.onclick = function () {
if(index) {
index--;
animation(ulObj, -index*moveWidth);
}
};
// 右移
rightObj.onclick = function () {
if(index<ulObj.children.length-1) {
index++;
animation(ulObj, -index*moveWidth);
}
};
// 封装动画移动函数
function animation(element, target) {
// 判断当前的位置
var current = element.offsetLeft;
var onestep = 17;
var timeId = setInterval(function () {
current += current < target ? onestep : -onestep;
if (Math.abs(current - target) >= onestep) {
element.style.left = current + "px";
} else {
clearInterval(timeId);
element.style.left = target + "px";
}
}, 10);
}
</script>
</body>
</html>
2.3.3、完整轮播图
需求:鼠标进入数字按钮自动切换;鼠标点击左右切换按钮切换,并且数字按钮跟着切换;自动轮播。
代码:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Title</title>
<link rel="stylesheet" href="base.css">
<style>
* {
margin: 0;
padding: 0;
}
#box {
width: 400px;
height: 250px;
margin: 100px 0 0 400px;
position: relative;
border: 2px solid #31608a;
overflow: hidden;
}
ul {
width: 1300px;
position: absolute;
}
li {
list-style-type: none;
float: left;
}
img {
width: 400px;
height: 250px;
}
.sp {
position: absolute;
left: 50%;
margin-left: -45px;
bottom: 10px;
}
span {
float: left;
width: 20px;
height: 20px;
background-color: #fff;
border-radius: 10px;
text-align: center;
font: 400 16px/20px Consolas;
margin: 0 5px 0 5px;
cursor: pointer;
}
.spdiv {
width: 400px;
height: 50px;
position: absolute;
top: 100px;
display: none;
}
#left {
width: 50px;
height: 50px;
float: left;
cursor: pointer;
text-align: center;
font: 400 28px/50px Consolas;
color: #fff;
background-color: rgba(255, 255, 255, 0.3);
}
#right {
float: right;
width: 50px;
height: 50px;
cursor: pointer;
text-align: center;
font: 400 28px/50px Consolas;
color: #fff;
background-color: rgba(255, 255, 255, 0.3);
}
.current {
background-color: red;
color: #fff;
}
</style>
</head>
<body>
<div id="box">
<ul>
<li><a href="#"><img src="images/img1.jpg" alt=""></a></li>
<li><a href="#"><img src="images/img2.jpg" alt=""></a></li>
<li><a href="#"><img src="images/img3.jpg" alt=""></a></li>
</ul>
<div class="sp">
<span class="current">1</span>
<span>2</span>
<span>3</span>
</div>
<div class="spdiv">
<s id="left"><</s>
<s id="right">></s>
</div>
</div>
<script src="common.js"></script>
<script>
// 获取box元素
var boxObj = my$("box");
// 获取ul元素,因为移动的就是整个ul
var ulObj = boxObj.children[0];
// 移动宽度
var moveWidth = document.getElementsByTagName("img")[0].offsetWidth;
// 获取ul中所有的li
var liObjs = ulObj.children;
ulObj.appendChild(liObjs[0].cloneNode(true)); // 克隆第一个li,加入到ul中的最后
ulObj.style.width = ulObj.offsetWidth + moveWidth + "px"; // 重新设置ul的宽度
// 获取所有span标签
var spanObjs = boxObj.children[1].getElementsByTagName("span");
// console.log(spanObjs);
// 获取spdiv标签
var spdivObj = boxObj.children[2];
// 获取span左标签
var leftObj = my$("left");
// 获取span右标签
var rightObj = my$("right");
var pos = 0;
var myTimeId = setInterval(moveRight, 1000);
// 自动播放 + 鼠标进入事件
boxObj.onmouseover = function () {
spdivObj.style.display = "block";
clearInterval(myTimeId);
};
boxObj.onmouseout = function () {
spdivObj.style.display = "none";
myTimeId = setInterval(moveRight, 1000);
};
// 左移
leftObj.onclick = function () {
if (pos === 0) {
pos = spanObjs.length;
ulObj.style.left = -spanObjs.length * moveWidth + "px";
}
pos--;
animation(ulObj, -pos * moveWidth);
for (var i = 0; i < spanObjs.length; i++) {
// 清空span背景
spanObjs[i].removeAttribute("class");
}
// 设置当前span标签
spanObjs[pos].className = "current";
};
// 右移
rightObj.onclick = moveRight;
function moveRight() {
if (pos === spanObjs.length) { // 在到达克隆的一张的时候,立即跳到第一张
pos = 0;
ulObj.style.left = 0 + "px";
}
pos++;
animation(ulObj, -pos * moveWidth);
if (pos === spanObjs.length) {
spanObjs[0].className = "current";
spanObjs[spanObjs.length - 1].className = "";
} else {
for (var i = 0; i < spanObjs.length; i++) {
// 清空span背景
spanObjs[i].removeAttribute("class");
}
// 设置当前span标签
spanObjs[pos].className = "current";
}
};
// 遍历所有的 span 标签
for (var i = 0; i < spanObjs.length; i++) {
// 获取每个span的编号,设置自定义属性
spanObjs[i].setAttribute("index", i + "");
spanObjs[i].onmouseover = function () {
for (var j = 0; j < spanObjs.length; j++) {
// 清空span背景
spanObjs[j].removeAttribute("class");
}
// 设置当前span标签
this.className = "current";
// 每个编号*移动的宽度就是移动到的目标位置
pos = this.getAttribute("index");
if (pos) {
animation(ulObj, -pos * moveWidth);
} else {
}
};
}
// 封装动画移动函数
function animation(element, target) {
// 判断当前的位置
var current = element.offsetLeft;
var onestep = 7;
var timeId = setInterval(function () {
current += current < target ? onestep : -onestep;
if (Math.abs(current - target) >= onestep) {
element.style.left = current + "px";
} else {
clearInterval(timeId);
element.style.left = target + "px";
}
}, 10);
}
</script>
</body>
</html>
1、首先获取所有需要的元素。
2、使用克隆第一个 li 标签来模拟从最后一个图片切换到第一个图片的过程。注意:这时候 ul 的宽度要改变,保证 li 的浮动在一行显示。
3、在右移最后一张过度到第二张的时候的处理方式为:当用户看到第一张的时候其实是最后一张,这个时候怎么过度到第二张?处理方法是,当在需要从最后一张跳转到第二张的时候,先让最后一张图切换到第一张,因为是克隆的,所以最后一张和第一张没有区别,用户看到的第一张其实是最后一张切换到了第一张,这个时候正常切换到第二张即可。
4、当需要点击左右切换按钮,需要数字按钮相对应的时候,注意第一个数字按钮和最后一个数字按钮的特殊处理。
5、图片下标 pos 是链接点击按钮和数字按钮的关键。
6、设置自动播放的时候,不使用定时器设置 pos 的方式,是因为当前 pos 的值不确定,使用自动点击右移按钮的方式。之所以设置两个 setInterval(moveRight, 1000); ,一个是进入页面自动播放,一个是鼠标退出 box 后的自动播放。
从零开始学 Web 之 BOM(二)定时器的更多相关文章
- 从零开始学 Web 之 BOM(三)offset,scroll,变速动画函数
大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...
- 从零开始学 Web 之 BOM(一)BOM的概念,一些BOM对象
大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... +-------------------------------------------------------- ...
- 从零开始学 Web 之 BOM(四)client系列
大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...
- 从零开始学 Web 系列教程
大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新…… github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:http:/ ...
- 从零开始学 Web 之 移动Web(二)JD移动端网页,移动触屏事件
大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...
- 从零开始学 Web 之 ES6(四)ES6基础语法二
大家好,这里是「 从零开始学 Web 系列教程 」,并在下列地址同步更新...... github:https://github.com/Daotin/Web 微信公众号:Web前端之巅 博客园:ht ...
- 从零开始学Web之HTML(二)标签、超链接、特殊符号、列表、音乐、滚动、head等
大家好,这里是 Daotin 从零开始学 Web 系列教程.此文首发于「 Daotin的梦呓 」,欢迎大家订阅关注.在这里我会从 Web 前端零基础开始,一步步学习 Web 相关的知识点,期间也会分享 ...
- 从零开始学 Web 之 CSS(二)文本、标签、特性
大家好,这里是「 Daotin的梦呓 」从零开始学 Web 系列教程.此文首发于「 Daotin的梦呓 」公众号,欢迎大家订阅关注.在这里我会从 Web 前端零基础开始,一步步学习 Web 相关的知识 ...
- 从零开始学 Web 之 DOM(二)对样式的操作,获取元素的方式
大家好,这里是「 Daotin的梦呓 」从零开始学 Web 系列教程.此文首发于「 Daotin的梦呓 」公众号,欢迎大家订阅关注.在这里我会从 Web 前端零基础开始,一步步学习 Web 相关的知识 ...
随机推荐
- spring 自定义标签的实现
在我们进行Spring 框架开发中,估计用到最多的就是bean 标签吧,其实在Spring中像<mvc/><context/>这类标签以及在dubbo配置的标签都是属于自定义的 ...
- pythone函数基础(9)操作数据库连接
#操作数据库连接import pymysqlconn = pymysql.connect(host='118.24.3.40',user='jxz', password='123456',port=3 ...
- jar与war包区别,转自https://www.jianshu.com/p/3b5c45e8e5bd
https://www.jianshu.com/p/3b5c45e8e5bd
- Quartz.NET快速入门指南
最近,在工作中遇到了 Quartz.net 这个组件,为了更好的理解项目代码的来龙去脉,于是决定好好的研究一下这个东西.确实是好东西,既然是好东西,我就拿出来分享一下.万丈高楼平地起,我们也从入门开始 ...
- 网络虚拟化技术(二): TUN/TAP MACVLAN MACVTAP (转)
网络虚拟化技术(二): TUN/TAP MACVLAN MACVTAP 27 March 2013 TUN 设备 TUN 设备是一种虚拟网络设备,通过此设备,程序可以方便得模拟网络行为.先来看看物理设 ...
- 开始Dev之路
从今天开始,开启Dev的发展之路.
- C++ 提取网页内容系列之四正则
标 题: C++ 提取网页内容系列之四作 者: itdef链 接: http://www.cnblogs.com/itdef/p/4173833.html 欢迎转帖 请保持文本完整并注明出处 将网页内 ...
- FTP服务与配置
FTP简介 网络文件共享服务主流的主要有三种,分别是ftp.nfs.samba. FTP是File Transfer Protocol(文件传输协议)的简称,用于internet上的控制文件的双向传输 ...
- 网站日志流量分析采集(LuaJIT系统环境部署-node03,相关jar包自己手动上传)
注:/usr/local/src 是源码包路径,可以自己更改 服务器中安装依赖 yum -y install gcc perl pcre-devel openssl openssl-devel 上传 ...
- Ubuntu Apache 不同端口监听不同站点
在/etc/apache2/apache2.conf 中,把项目根目录设置成默认的/var/www 不要设置在某个站点的路径下(我就是配置第一个站点时改了这里才会配置第二个站点时好久弄不出来) 在 / ...