po主比较懒,昨天出去玩耍,所以前天的笔记没有来得及整理。现在发上来吧。
这一章主要是关于计时器的学习,其中包括set Interval与setTimeout,以及利用这两个方法实现的一些动画小案例。
话不多说,直接上笔记
1.定时器
1.1 通过js,我们有能力做到在一个设定的时间间隔之后来执行一段程序,而不是在函数调用之后立即执行,我们称之为计时事件
1.2 定时器就是在指定时间间隔后来执行函数。
setTimeout:setTimeout(参数1,参数2);延时调用,只执行一次
参数1:函数、函数名称;
参数2:指定时间(单位是毫秒)1s==1000ms
function print(){console.log("打印了")}
setTimeout(print,1000);
setInterval:setInterval(参数1,参数2);重复执行
参数1:函数、函数名称;
参数2:指定时间,单位是毫秒,1s===1000ms
function print(){console.log("打印了")}
var timer = setInterval(print,1000);
停止计时器
clearInterval(timer);
1.3 关于计时器的小练习,可以参考W3C
2.封装使用ID获取标签的方法###
包括但不局限于ID的封装,前面的笔记中有一个关于利用class属性来获取指定标签的封装,有需要的童鞋也可以去看看。
封装:function $(id){return document.getElementById(id)};
使用:var box = $("box");
3.动画###
3.1 定时器在使用之前必须先停止计时器
3.2 匀速动画
利用计时器改变目标标签的位置,以步长为属性进行累加直到目标标签达到指定位置
CSS代码:
*{
margin: 0;
padding: 0;
}
#box{
width: 100px;
height: 100px;
background: #000;
}
HTML代码:
<button id="btn">点击按钮开始匀速动画</button>
<div id="box"></div>
JS代码:
function $(id){return document.getElementById(id);}
var btn = $("btn"),div = $("box");
var step = 0,target = 600,timer = null;
btn.onclick = function () {
clearInterval(timer);
timer = setInterval(function () {
step+=2;
if(step>=600){
step=600;
clearInterval(timer);
}
div.style.marginLeft=step+"px";
},10)
}
3.3 减速动画
运动学公式
var leader = 0;
var target = 600;
var sport = (target - leader) / 10;
leader = leader+sport; //leader+=sport;
在上面的代码中,我们如果打印一下sport的值,将会发现sport是一个由大逐渐变小的过程。就达到了减速动画的效果。下面我们来看一段demo:
CSS代码:
*{
margin: 0;
padding: 0;
}
#box{
width: 100px;
height: 100px;
background: greenyellow;
}
HTML代码:
<button id="btn">点击按钮开始减速运动</button>
<div id="box"></div>
JS代码:
function $(id){return document.getElementById(id);}
var btn = $("btn"),box = $("box");
var target = 600,leader = 0,timer =null;
btn.onclick= function () {
clearInterval(timer);
timer = setInterval(function () {
if(Math.round(leader)==600){
clearInterval(timer);
leader=600;
}
leader+=(target-leader)/50;
box.style.marginLeft = leader+"px";
},30);
}
当然,细心的童鞋已经发现了,虽然leader的值虽然无限接近于我们的目标值target,但由于每次目标值减去运动的值再除以十,就不可能会得到目标值,所以我们会陷入一个无限循环的步骤中,那么我们就对leader进行四舍五入操作,当他接近目标值时就直接对其四舍五入等于目标值,那么运动到此为止就可以结束了。大家可以自己尝试一下哟。
4. Math对象###
4.1 Math.round(); //对小数进行四舍五入操作
4.2 Math.random()*10; //随机产生一个0到10之间的浮点数,不包括10
5. 小米广告/窗帘效果
又是一个练手的demo,就不那么多废话了。直接看一下缩写版的操作步骤吧。
布局
鼠标放入box后img的位置的计算
鼠标移出后停止位置的改变
出现诡异情况时,请清空计时器
改变位置时的步长
CSS代码:
*{
margin: 0;
padding: 0;
}
div{
width: 512px;
height: 400px;
border: 1px solid #000;
-webkit-box-sizing: border-box;
-moz-box-sizing: border-box;
box-sizing: border-box;
margin: 100px auto;
overflow: hidden;
position: relative;
}
div span{
position: absolute;
left:0;
width:100%;
height:200px;
cursor: pointer;
}
div span:nth-of-type(1){
top:0;
/*background: red;*/
}
div span:nth-of-type(2){
top:200px;
/*background: blue;*/
}
div img{
position: absolute;
top:0;
left:0;
}
HTML代码:
<div>
![](images/mi.png)
<span></span>
<span></span>
</div>
JS代码:
var img = document.getElementsByTagName("img")[0];
var box = document.getElementsByTagName("div")[0];
var spanTop = document.getElementsByTagName("span")[0];
var spanBottom = document.getElementsByTagName("span")[1];
var timer = null;
var leader = 0;
// console.log( leader > -parseInt(img.offsetHeight - box.offsetHeight));
//鼠标位于广告图上半部分时
spanTop.onmouseover= function () {
clearInterval(timer);
timer = setInterval(function () {
// console.log(leader);
if(leader > -parseInt(img.offsetHeight - box.offsetHeight)){
leader-=1;
}
else{
leader = -(parseInt(img.offsetHeight - box.offsetHeight));
clearInterval(timer);
}
img.style.top=leader+"px";
},3);
};
spanTop.onmouseout= function () {
clearInterval(timer);
};
//鼠标位于广告图下半部分时
spanBottom.onmouseover = function () {
clearInterval(timer);
timer = setInterval(function () {
if(leader<0)leader+=1;
else {
leader=0;
clearInterval(timer);
}
img.style.top=leader+"px";
},3)
};
spanBottom.onmouseout = function () {
clearInterval(timer);
};
orz,时隔两天再看自己的代码,惨不忍睹,冗余太多。书写的也很差劲,后面会多写代码提升自己代码的可阅读性。
6. 倒计时跳转页面###
页面提示:将在几秒后跳转到某个页面,几是一直变化的值
利用到window对象的location属性
window.location.href = "http://www.baidu.com/"
<button>点击开始计时</button>
<p>页面将在5s后跳转至百度</p>
<script>
var btn = document.getElementsByTagName("button")[0];
var p = document.getElementsByTagName("p")[0];
var str = p.innerText;
var second = 0;
for(var i=0;i<str.length;i++){
if(parseInt(str.charAt(i),10))
second = parseInt(str.charAt(i));
}
方案一:settimeout实现,递归函数
function loadBd(){
second--;
console.log(second);
if(!second){
window.location.href="http://www.baidu.com/";
}
else
{
p.innerText = "页面将在"+second+"s后跳转至百度";
setTimeout(loadBd,1000);
}
}
btn.onclick=loadBd;
方案二:setInterval实现
/*
var timer = null;
btn.onclick= function () {
clearInterval(timer);
timer = setInterval(function () {
// --second;
p.innerText = "页面将在"+--second+"s后跳转至百度";
if(!second)window.location.href="http://www.baidu.com/";
},1000);
}
*/
7.简单的轮播###
从右向左滚动,注意图片的衔接
布局需要注意,用前面的图片去衔接到最后一张图片以后,避免跳转时的尴尬。
<ul>
<li>
</li>
<li>
<li>
<li>
</li>
</ul>
滚动超出显示框长度时重置ul位置
CSS代码
*{
margin: 0;
padding: 0;
}
div{
border: 1px solid #000;
width: 600px;
height: 200px;
margin: 0 auto;
position: relative;
overflow: hidden;
top: 100px;
}
div ul{
width: 400%;
position: absolute;
top: 0;
left: 0;
}
div ul li{
list-style:none;
float: left;
cursor: pointer;
user-select: none;
}
HTML代码:
<div>
<ul>
<li>![](images/lunbo/01.jpg)</li>
<li>![](images/lunbo/02.jpg)</li>
<li>![](images/lunbo/03.jpg)</li>
<li>![](images/lunbo/04.jpg)</li>
<li>![](images/lunbo/01.jpg)</li>
<li>![](images/lunbo/02.jpg)</li>
</ul>
</div>
JS代码:
var ul = document.getElementsByTagName("ul")[0];
var timer = null, leader = 0;
function lb(){
clearInterval(timer);
timer = setInterval(function () {
leader=leader==-1190?leader=0:leader-=5;
ul.style.left = leader+"px";
},30);
}
lb();
document.getElementsByTagName("div")[0].onmouseover = function () {
clearInterval(timer);
};
document.getElementsByTagName("div")[0].onmouseout = function () {
lb();
};
8.淘宝广告图的轮播###
注意排他思想的时候,以及定义一个变量用作索引保存当前所展示图片的位置
CSS代码:
*{
margin: 0;
padding: 0;
}
.box{
width: 300px;
height: 250px;
margin: 100px auto;
border: 1px solid #000;
cursor: pointer;
}
.box li{
list-style-type: none;
line-height:27px;
border-bottom: 1px solid #000;
text-align: center;
}
.box li:nth-child(9),
.box li:nth-child(18){
border-bottom:none;
}
.box ul:nth-of-type(1){
float: left;
width: 50px;
}
.box ul:nth-of-type(2){
float: right;
}
.box img{
border-right: 1px solid #000;
border-left: 1px solid #000;
margin: 0 auto;
}
.current{
background: url("images/taobao/bg.gif") repeat-x;
}
HTML代码:
<div class="box">
<ul>
<li class="current">冬裙</li>
<li>呢大衣</li>
<li>围巾</li>
<li>女包</li>
<li>女裤</li>
<li>女靴</li>
<li>棉服</li>
<li>毛衣</li>
<li>牛仔裤</li>
</ul>
![](images/taobao/冬裙.jpg)
<ul>
<li>男包</li>
<li>男棉服</li>
<li>男毛衣</li>
<li>男靴</li>
<li>登山鞋</li>
<li>皮带</li>
<li>皮衣</li>
<li>羽绒服</li>
<li>雪地靴</li>
</ul>
</div>
JS代码:
var lis = document.getElementsByTagName("li");
var img = document.getElementsByTagName("img")[0];
var box = document.getElementsByClassName("box")[0];
var imgSrcArr = ["images/taobao/冬裙.jpg","images/taobao/呢大衣.jpg","images/taobao/围巾.jpg","images/taobao/女包.jpg","images/taobao/女裤.jpg","images/taobao/女靴.jpg","images/taobao/棉服.jpg","images/taobao/毛衣.jpg","images/taobao/牛仔裤.jpg","images/taobao/男包.jpg","images/taobao/男棉服.jpg","images/taobao/男毛衣.jpg","images/taobao/男靴.jpg","images/taobao/登山鞋.jpg","images/taobao/皮带.jpg","images/taobao/皮衣.jpg","images/taobao/羽绒服.jpg","images/taobao/雪地靴.jpg"];;
var loop=0;
var timer = null;
function tb() {
timer = setInterval(function () {
loop++;
if (loop==18)loop=0;
for(let i = 0; i < lis.length; i++){
lis[i].className = "";
}
img.src = imgSrcArr[loop];
lis[loop].className = "current";
},1000);
};
tb();
box.onmouseover= function () {
clearInterval(timer);
};
box.onmouseout= function () {
tb();
}
9.左右向轮播
节流思想
原理:当进入轮播事件时,判断flag的值,如果真,则直接跳出函数,如果假,那么设置为真并执行函数内容,当函数所展现结果达到预期值,则改变flag值使其可以再次进入函数
方法一:图片总数+1个li的轮播
CSS代码:
*{
margin: 0;
padding: 0;
}
#box{
border: 1px solid #000;
width: 640px;
height: 270px;
position: relative;
margin:100px auto;
overflow: hidden;
}
#box ul{
width: 800%;
position: absolute;
left:0;
top: 0;
}
#box ul li{
float: left;
list-style:none;
}
#box span{
font-size:60px;
color: white;
background: rgba(0,0,0,.5);
position: absolute;
cursor: pointer;
}
#box span:nth-of-type(1){
top:105px;
left:0;
}
#box span:nth-of-type(2){
top:105px;
right:0;
}
HTML代码:
<div id="box">
<ul>
<li>![](images/zuoyouLunBo/01.jpg)</li>
<li>![](images/zuoyouLunBo/02.jpg)</li>
<li>![](images/zuoyouLunBo/03.jpg)</li>
<li>![](images/zuoyouLunBo/04.jpg)</li>
<li>![](images/zuoyouLunBo/05.jpg)</li>
<li>![](images/zuoyouLunBo/01.jpg)</li>
</ul>
<span><</span>
<span>></span>
</div>
JS代码:
//获取所需要用到的元素
var ul = document.getElementsByTagName("ul")[0];
var span = document.getElementsByTagName("span");
var left = span[0],right = span[1];
//节流思想
var flag = false;
//设置轮播图所需要用到的变量
var timer = null, loop = 0, step = 640, sign = 0; //loop为当前box中即将要显示图片的索引值,step为每张图的宽度,sign为改变ul位置的中间值
//右边span点击时响应事件
right.onclick = function () {
if(flag)return; //节流思想的调用,防止多次点击轮播图会多次滚动,每次轮播都需要在当前轮播完成以后才可以开始。原理:当进入轮播事件时,判断flag的值,如果真,则直接跳出函数,如果假,那么设置为真并执行函数内容,当函数所展现结果达到预期值,则改变flag值使其可以再次进入函数
flag =true;
clearInterval(timer); //每次执行代码前先清空一遍计时器,否则会出现计时器多次启动的奇怪现象
loop++; //每次点击以后loop索引自动加1,对应当前所显示图片索引位置
if(loop>5){ //当索引达到图片张数最大时,loop则改变为1,意为接下来要显示第二张图,并且sign变为0,从第一张图过度到第二张图
loop = 1;
sign = 0;
}
timer = setInterval(function () {
sign -= 1; //ul向左滚动,每30毫秒移动1个像素
if(sign < -loop * step){ //当sign值小于loop个图片宽度时候,sign则等于loop个图片宽度的绝对值
sign = -loop * step;
flag = false;
clearInterval(timer);
}
ul.style.left = sign +"px"; //改变ul的位置为sign的值
},2); //每2毫秒改变一次轮播图位置
};
//左边span点击时响应事件
left.onclick = function () { //执行体逻辑同右边span点击相似,不赘述
if(flag)return;
flag = true;
clearInterval(timer);
loop--; //当前索引向前滚
if (loop<0){ //当前显示图片位置如果比第一张小,则让他变成第五张图片,并且sign变为过度图片所在位置,之后由于定时器的原因会继续向第五张图片方向滚动
loop = 4;
sign = -(loop+1) * step;
}
timer = setInterval(function () {
sign += 1; //图片从左向右移动,sign的值是递增的过程,当他大于当前即将显示图片位置时,则sign的值更改为当前所显示图片的位置
if(sign>-loop*step){
sign = -loop*step;
clearInterval(timer);
flag = false;
}
ul.style.left = sign + "px";
},2)
}
方法二:两个li的轮播方式
CSS代码:
*{
margin: 0;
padding: 0;
user-select: none;
}
#box{
border: 1px solid #000;
margin: 100px auto;
width: 640px;
height: 270px;
position: relative;
overflow: hidden;
}
#box ul{
width: 220%;
position: absolute;
top: 0;
left: 0;
}
#box ul li{
float: left;
list-style:none;
}
#box span{
position: absolute;
font-size:60px;
background: rgba(0,0,0,.5);
color: #fff;
cursor: pointer;
}
#box span:nth-of-type(1){
top: 105px;
left: 0;
}
#box span:nth-of-type(2){
top: 105px;
right: 0;
}
HTML代码:
<div id="box">
<ul>
<li>![](images/zuoyouLunBo/01.jpg)</li>
<li>![](images/zuoyouLunBo/02.jpg)</li>
</ul>
<span><</span>
<span>></span>
</div>
JS代码:
//获取所需要的标签
var span = document.getElementsByTagName("span");
var left = span[0], right = span[1];
var ul = document.getElementsByTagName("ul")[0];
var img = document.getElementsByTagName("img");
var img1 = img[0], img2 = img[1];
//准备轮播图切换时所需要的数据
var imgSrcArr = [
"images/zuoyouLunBo/01.jpg",
"images/zuoyouLunBo/02.jpg",
"images/zuoyouLunBo/03.jpg",
"images/zuoyouLunBo/04.jpg",
"images/zuoyouLunBo/05.jpg",
"images/zuoyouLunBo/01.jpg",
];
//准备轮播图所需要的变量
var timer = null, loop = 0, leader = 0; //loop表示即将要显示的图片在数组重的索引,leader为改变ul位置的中间值
//节流思想
var flag = false;
//右边按钮点击时所响应事件
right.onclick= function () {
if(flag)return; //节流思想的使用
flag = true;
clearInterval(timer); //每次点击都先清空一遍计时器,以保证多次点击不会开启多个计时器
loop++; //每次点击以后要显示图片的索引
if(loop ==5)loop = 0; //当图片到达最后一张时,那么即将显示的图片则为第一张
timer = setInterval(function () { //设置一个定时器,用来改变ul所在的位置与对应的li中所显示的图片
leader-=15; //图片向左移动,则ul的left位置会越来越小
if(leader < -640){ //当向左移动的位置刚好达到一张图片的距离时,停止运动,并将ul放回原位,同时修改两个img标签所对应的路径为正确的图片
clearInterval(timer);
img1.src = imgSrcArr[loop];
img2.src = imgSrcArr[loop+1];
leader = 0;
flag = false;
}
ul.style.left = leader + "px";
},30);
};
//左边按钮点击时所响应事件
left.onclick = function () {
if(flag)return; //节流思想的使用
flag = true;
clearInterval(timer);
loop--; //每次点击后要显示的图片的索引值自行更改,点击左边那么ul向右滚动
if(loop<0)loop=4; //当点击完第一张后,即将显示的应为最后一张
leader = -640; //每次点击左边时都将ul向左放置一张轮播图的宽度,如果非固定图片,那么此时该值被称为魔鬼数字,应用变量替换掉。
timer = setInterval(function () { //设置一个计时器,ul的left值在-640的基础上每30毫秒向右滚动30个像素,当ul的left值大于一个图片宽时,将ul的left值设为零并清空计时器
leader+=30;
img1.src = imgSrcArr[loop]; //修改两张图片的src属性,以改变显示的图片内容 此处有个小bug,将更改图片路径的两条语句写在setInterval外部会导致轮播图出现闪烁的情况,内部则根据预期目标实现效果
img2.src = imgSrcArr[loop+1];
if(leader>0){
clearInterval(timer);
flag = false;
leader = 0;
}
ul.style.left = leader + "px";
},30);
}