## 动画(熟悉)
### 让每一个元素记录一个定时器
在上一节的学习中,我们将动画封装到了一个animate函数中。这种封装动画的方式存在一个存在一个问题,即此时的animate函数只能针对一个元素开启一个定时器来执行动画,如果想在页面中同时让多个div的运动起来,做不到!此时我们就需要改进animate函数了。那如何才能让也个页面中的多个元素同时运动起来呢?
现在的animate做不到让多个元素同时运动,是因为我们的timeId是共享的,假如每个元素能存储自己的timeId,这个问题就能解决了。让元素存储timeId其实就是将timeId存储到元素的属性中,所以我们可修改代码为如下。
**需求:**让每一个元素记录一个定时器;
html和css代码
~~~
<style>
#box {
position: relative;
background-color: red;
width: 100px;
height: 100px;
}
#box2 {
position: relative;
background-color: blue;
width: 100px;
height: 100px;
}
</style>
<input type="button" value="移动400" id="btn">
<input type="button" value="移动800" id="btn2">
<div id="box"></div>
<div id="box2"></div>
~~~
JavaScript代码
~~~
//需求:让每一个元素记录一个定时器
var btn = document.getElementById('btn');
var btn2 = document.getElementById('btn2');
var box = document.getElementById('box');
var box2 = document.getElementById('box2');
// 1、点击按钮,div向右移动
btn.onclick = function () {
animate(box, 400, 10);
}
btn2.onclick = function () {
animate(box2, 800, 3);
}
// var timeId = null;
//封装动画代码到函数中
function animate(element, target, frequency){
//判断当前文档中是否已经启用定时器,如果启用,则先销毁,保证当前点文档中只有一个定时器在执行动画
if (element.timeId) {
clearInterval(element.timeId);
element.timeId = null;
}
// 2、div不停地向右移动
element.timeId = setInterval(function () {
//步进,开发中,不应该写死数据
var step = 3;
var current = element.offsetLeft;
// 3、div移动到指定的位置,停止移动
//如果等于500,就停止移动
if (element.offsetLeft >= target) {
clearInterval(element.timeId);
element.style.left = target + 'px';
return;
}
//累加步长
current += step;
element.style.left = current + 'px';
}, frequency);
}
~~~
### 完善动画
以上代码解决了一个页面总只能执行一个动画的问题。现在,新的问题又来了,当我们使用两个按钮控制一个div运动时,当点击"移动800"时,div正常地移动到了800的位置,此时当点击"移动400"时,div一瞬间跳回了400的位置,这就是问题了!当点击"移动400"时,我么需要的是div以动画方式缓缓地移动回400的位置。怎么实现这样的效果呢?
**需求:**让div从800的位置缓缓移动到400的位置;
**思路:**div在800的位置,当点击"移动400"时,只需将div的left从800慢慢递减到400,即可;
html和css代码
~~~
<style>
#box {
position: relative;
background-color: red;
width: 100px;
height: 100px;
}
#box2 {
position: relative;
background-color: blue;
width: 100px;
height: 100px;
}
</style>
<input type="button" value="移动400" id="btn">
<input type="button" value="移动800" id="btn2">
<div id="box"></div>
~~~
JavaScript代码
~~~
//需求:让每一个元素记录一个定时器
var btn = document.getElementById('btn');
var btn2 = document.getElementById('btn2');
var box = document.getElementById('box');
// var box2 = document.getElementById('box2');
// 1、点击按钮,div向右移动
btn.onclick = function () {
animate(box, 400, 30);
}
btn2.onclick = function () {
animate(box, 800, 30);
}
// var timeId = null;
//封装动画代码到函数中
function animate(element, target, frequency){
//判断当前文档中是否已经启用定时器,如果启用,则先销毁,保证当前点文档中只有一个定时器在执行动画
if (element.timeId) {
clearInterval(element.timeId);
element.timeId = null;
}
// 2、div不停地向右移动
element.timeId = setInterval(function () {
//步长,开发中,不应该写死数据
var step = 10;
var current = element.offsetLeft;
//当当前位置 > 目标位置时, 步长 step 取负数
if(current > target){
step = -Math.abs(step);
}
// 3、div移动到指定的位置,停止移动
//当当前位置-目标位置 的绝对值小于或等于step的绝对值,则说明应该停止移动了
// Math.abs(current - target) <= Math.abs(step);
if (Math.abs(current - target) <= Math.abs(step)) {
clearInterval(element.timeId);
element.style.left = target + 'px';
return;
}
//累加步长
current += step;
element.style.left = current + 'px';
}, frequency);
}
~~~
### 解决动画往回移动慢的问题
~~~
当div的left和offleft不同步或者并不相等时,会导致div从800移动到400时的速度很慢。此时需要在页面中加入样式 body { margin: 0; },将left的值和offset的值都是从0开始,这样就解决了问题。
~~~
最后我们得到的animate函数就是移动元素通用的函数了。所有我们可以将animate函数抽取到js文件中,以供将来重复调用。
## 需求
## 需求
注意,以下需求的代码实现在当天的项目中。
### 无缝轮播图(掌握)
~~~
================05_轮播图-动态生成序号================
分析文档HTML和css结构,归纳出代码思路:
1、动态生成序号
2、点击序号,以动画的方式切换到相应图片
3、鼠标放到盒子上显示箭头
4、实现上一张和下一张的功能
5、自动切换图片
以下对思路进行代码实现:
1、动态生成序号
(1)获取页面上ul中的li个数,作为序号的个数,生成序号
(2)默认序号1高亮显示,两种方式
================06_轮播图-点击序号================
2、点击序号,动画的方式切换到图片
问题:在li上注册点击事件,点击序号时,具体做什么?
2.1 取消其他li的高亮显示,让当前li高亮显示
2.2 点击序号,动画的方式切换到当前点击的图片
设置li的自定义属性,用于记录li的索引
获取自定义属性,移动的距离 = li的索引 * 图片宽度
注意:调用animate函数,移动的方向:往前是负数,往后是正数
================07_轮播图-显示箭头01================
3、鼠标放到盒子上显示箭头
到此为止,我们好像做了很多分析,写了很多代码。我们把每个大的问题分解成了几个小问题,实际上每个小问题的解决所写的代码并不多。
==============08_轮播图-上一张和下一张===============
arrow:箭头
4、实现上一张和下一张的功能
思路一:当点击箭头时,获取当前选中的图片索引,索引+1并将图片切换一个图片的长度,此种做法可行,但是需要遍历获取到当前选中的li;
思路二:从索引为0的那张图片开始,每点击一次箭头,就调用一下animate做相应方向、大小的移动。
问题:无缝滚动问题比较复杂,先不做。
可以先采用这样的方式实现:当移动到最后一张图片时,再点击下一张箭头,图片不动
问题:图片切换之后,对应图片的序号没有高亮显示。
解决:使用click()方法触发当前元素的点击事件来完成点击,既解决图片切换问题,又解决序号高亮显示问题。
================11_轮播图-下一张无缝滚动================
4、实现上一张和下一张的功能
刚开始接触这样的需求,如果没思路没关系,但是当我们分析了分析了之后,就要会独立去分析类似的问题,并解决问题。
无缝滚动实现方式:
页面加载完成时,复制第一张图片衔接到最后一张图片后面;此时,当点击下一张按钮时,将图片切换到最后一张图片上(也就是html中多复制出来的那一张),当再点击下一张时,将ul的外置瞬间改变成显示第1张图片的位置,然后切换到第2张图片。
================12_轮播图-上一张无缝滚动================
当点击上一张按钮时,如果当前是第1张图片,此时要在一瞬间将第1张切换到最后一张图片的位置,
================13_轮播图-自动播放================
隔1秒切换到下一张,使用定时器完成。
思路:隔1秒中,点击(使用click方法)一下按钮;
问题:鼠标放到图片上时,没有停止滚动
解决:当鼠标放到图片上时,清除定时器;当鼠标移出图片时,启动定时器执行动画。
~~~
### 回到顶部(掌握)
~~~
================15_回到顶部01================
以前:代码都是放到一个文件夹下,比较乱。
现在:把案例看做一下项目,文件分类,放到不同文件夹中,方便开发人员查找文件、维护代码。
1、当拖动滚动条时,当页面(内容)滚动出去10px的时候,改变top的高度,并显示回到顶部的按钮;
问题:如何获取页面滚动出去的距离?
document.body.scrollTop;
documentElement 网页中的根元素html
document.documentElement
common中已经做了兼容性处理
注意:top是window对象中的只读属性,自定义名称不能为top,否则无法赋值
2、当点击回到顶部按钮时,动画的方式,回到最上面,让页面滚动距离为0;
================16_回到顶部02================
2、当点击回到顶部按钮时,动画的方式,回到最上面,让滚动距离为0;
使用简单动画的逻辑,参考animate()函数。
~~~