运动的要素
迭代量 (匀速运动(迭代量不变)缓冲运动(迭代量要越来越小))
终止条件 (当前的位置到达目标位 清除定时器)
当前位置 (当前位置 = 上一个位置+迭代量)
时间 (定时器)
匀速运动
示例
控制一个盒子从左移动到右 到达500的时候停止运动
初始位置为0、 目标位置为500、 迭代量是10
<div></div>
<script>
//获取元素div
var div = document.querySelector('div')
//已知条件 初始位置为0、 目标位置为500、 迭代量是10
var current = 0
var target = 500
var step = 10
//设置定时器
var timer = setInterval(function () {
//在定时器内 控制对应的位置的变化
//当前位置发生变化
current += step
//设置给对应的div
div.style.left = current + 'px'
//当到达目标位置的时候终止对应的定时器
if(current == target){
clearInterval(timer)
}
},20)
</script>
</body>
封装匀速运动
//获取样式的方法
function getStyle(ele) {
return getComputedStyle ? getComputedStyle(ele) : ele.currentStyle
}
//封装一个匀速运动的方法 传入元素对象 目标对象 left:300
function uniform(element, target,time=20) {
//清除上一次的影响
clearInterval(element.timer) //element.timer保证定时器唯一
//设置定时器
element.timer = setInterval(function () {
var flag = true //判断是否全部到达目标位置
//遍历target里面key
for (var key in target) {
//获取当前位置
var current = parseInt(getStyle(element)[key])
//当前位置如果小于目标位置 那么对应的step值是正的 否则是负
var step = current < target[key] ? 10 : -10
//在定时器内 控制对应的位置的变化
//当前位置发生变化
//设置给对应的div
element.style[key] = current + step + 'px'
//判断是否到达目标位置
if (current + step != target[key]) {
flag = false
}
}
// 当到达目标位置的时候终止对应的定时器
if(flag){
clearInterval(element.timer)
}
}, time)
}
缓冲运动
迭代量 ((目标位置-当前位置)/10)
示例
缓冲运动的透明度变化 (将对应的步长和对应的current先乘以100 再除100的操作)
<div></div>
<script>
//控制div的透明度变化
//获取div
var div = document.querySelector('div')
//读取当前值
var current = 0.75
//读取目标值
var target = 0.5
//设置定时器
var timer = setInterval(function () {
//在定时器内容设置对应的step
var step = (target - current)*100 / 10 // 0.01 - 0.1
//小于0向下取整 大于0向上取整 除以100 为了保证他取值范围在 0.01 - 0.1
step = step<0?Math.floor(step):Math.ceil(step)
//将步长和对应的当前的opacity先乘以100 再除100
current = parseInt(current*100+step)/100
//在定时器内设置对应的样式
div.style.opacity = current
//到达位置清除对应的定时器
if (current == target) {
clearInterval(timer)
}
}, 1000)
</script>
缓冲运动的封装
//运动的元素 目标对象
function bufferAnimation(element, targetObj) {
//清除上一次的定时器
clearInterval(element.timer)
//设置当前定时器
element.timer = setInterval(() => {
//获取当前的target目标值
var flag = true //记录当前是否全部完成
//遍历target对象
for (var key in targetObj) {
//获取当前的目标值
var target = targetObj[key]
//获取当前的位置
var current = parseFloat(getStyle(element)[key])
//设置步长 (目标值-当前值)/10
var step = target > current ? Math.ceil((target - current) / 10) :
Math.floor((target - current) / 10)
//传入key 为 left top width height... 传统的需要带上px为单位
if (key == 'left' || key == 'top' || key == 'width' || key =='hei gt') {
//设置对应的位置
current = current + step + 'px'
}
//如果传入的是opacity 没有单位 以及变化量要乘以100 再除100
else if (key == 'opacity') {
//小于0向下取整 大于0向上取整 除以100 为了保证他取值范围在 0.01 - 0.1
step = target < current ? Math.floor((target - current) * 100 /
10) : Math.ceil((target - current) * 100 / 10)
//将步长和对应的当前的opacity先乘以100 再除100
current = parseInt(current * 100 + step) / 100
}
//如果传入的color 或者是 zIndex 直接设置
else {
//直接设置
current = target
}
//将对应的样式设置
element.style[key] = current
//判断是否完成
if(parseFloat(getStyle(element)[key]) != target){
flag = false
}
}
//判断是否全部完成
if(flag){
clearInterval(element.timer)
}
}, 20)
}
//获取当前样式的方法
function getStyle(ele) {
return getComputedStyle ? getComputedStyle(ele) : ele.currentStyle
}
链式运动
概述:上一个完成继续下一个 像链子一样衔接运行
主要是通过对应的回调函数来完成对应的链式运动操作
// 运动 利用定时器来让对应的元素位置发生变化 由于定时器是异步 我不知道他什么时候执行完
function fn(callback){
setTimeout(() => {
console.log(1)
//将第二个定时器的代码放入到第一个定时器里面最后执行
setTimeout(() => {
console.log(2)
console.log(3)
callback()//将函数或者代码放入到对应的异步代码里面的最后执行 就可以将我们的代码
同步执行 回调函数 最后调用的函数
}, 2000)
}, 2000)
}
运动分类
匀速运动 (迭代量不变)
缓冲运动 (迭代量越来越小)
链式运动 (通过回调函数来执行下一个动画)
轮播图
控制对应的图片轮播,主要的方式有:
位置变化轮播
透明度轮播
图片切换轮播
位置变化轮播
要将对应的图片放在一行(横向)或者一列(纵向)
实际控制移动的是外面的大盒子(定位)的移动 (切换对应的left值 或者是top值)
大盒子的定位要基于展示的盒子
<!-- 用于展示的盒子 -->
<div class="show">
<ul class="content">
<li>
<img src="//img14.360buyimg.com/pop/s1180x940_jfs/t1/78233/4/23310/55539/63e0dc1dF618631fe/6fd733fb64b9743f.jpg.webp"alt="">
</li>
<li>
<img src="//img14.360buyimg.com/pop/s1180x940_jfs/t1/78233/4/23310/55539/63e0dc1dF618631fe/6fd733fb64b9743f.jpg.webp"alt="">
</li>
<li>
<img src="//img14.360buyimg.com/pop/s1180x940_jfs/t1/78233/4/23310/55539/63e0dc1dF618631fe/6fd733fb64b9743f.jpg.webp"alt="">
</li>
<li>
<img src="//img14.360buyimg.com/pop/s1180x940_jfs/t1/78233/4/23310/55539/63e0dc1dF618631fe/6fd733fb64b9743f.jpg.webp"alt="">
</li>
<li>
<img src="//img14.360buyimg.com/pop/s1180x940_jfs/t1/78233/4/23310/55539/63e0dc1dF618631fe/6fd733fb64b9743f.jpg.webp"alt="">
</li>
</ul>
</div>
</body>
<script src="./animated.js"></script>
<script>
//获取对应的ul这个元素
var ul = document.querySelector('.content')
//获取对应的显示的盒子的大小
var show = document.querySelector('.show')
var width = show.clientWidth
var height = show.clientHeight
//设置对应的定时器控制ul的移动
//用一个下标来表示对应切换的图片是哪一张
var index = 0
setInterval(()=>{
// ul.style.left = -1 * width * index +'px'
bufferAnimation(ul,{
left: -1 * width * index
})
index++
//如果到达最后一张变成第一张
if(index>4){
index = 0
}
},2000)
</script>
</html>
透明度轮播
控制对应的li的透明度变化
第一个切换到第二个的时候 第一个需要隐藏 第二个需要显示
<!-- 用于展示的盒子 -->
<div class="show">
<ul class="content">
<li>
<img src="//img14.360buyimg.com/pop/s1180x940_jfs/t1/78233/4/23310/55539/63e0dc1dF618631fe/6fd733fb64b9743f.jpg.webp"alt="">
</li>
<li>
<img src="//img14.360buyimg.com/pop/s1180x940_jfs/t1/78233/4/23310/55539/63e0dc1dF618631fe/6fd733fb64b9743f.jpg.webp"alt="">
</li>
<li>
<img src="//img14.360buyimg.com/pop/s1180x940_jfs/t1/78233/4/23310/55539/63e0dc1dF618631fe/6fd733fb64b9743f.jpg.webp"alt="">
</li>
<li>
<img src="//img14.360buyimg.com/pop/s1180x940_jfs/t1/78233/4/23310/55539/63e0dc1dF618631fe/6fd733fb64b9743f.jpg.webp"alt="">
</li>
<li>
<img src="//img14.360buyimg.com/pop/s1180x940_jfs/t1/78233/4/23310/55539/63e0dc1dF618631fe/6fd733fb64b9743f.jpg.webp"alt="">
</li>
</ul>
</div>
</body>
<script src="./animated.js"></script>
<script>
//获取对应的ul下面的所有li
var lis = document.querySelector('.content').children
//定时器控制对应的li变化
//记录对应的下标
var index = 0
setInterval(()=>{
//前一张的index
prevIndex = index
//当前的index
index ++
if(index>=lis.length){
index = 0
}
//先隐藏前一张 再显示第二张
bufferAnimation(lis[prevIndex],{
opacity:0
},()=>{
})
bufferAnimation(lis[index],{
opacity:1
})
},2000)
</script>
切换图片轮播
控制对应的图片的切换
<!-- 用于展示的盒子 -->
<div class="show">
<img src="//img14.360buyimg.com/pop/s1180x940_jfs/t1/78233/4/23310/55539/63e0dc1dF618631fe/6fd733fb64b9743f.jpg.webp"alt="">
</div>
</body>
<script src="./animated.js"></script>
<script>
var imgs = ['
//img14.360buyimg.com/pop/s1180x940_jfs/t1/78233/4/23310/55539/63e0dc1dF618631
fe/6fd733fb64b9743f.jpg.webp',
'
//imgcps.jd.com/ling4/10035789319416/5Lqs6YCJ5aW96LSn/5L2g5YC85b6X5oul5pyJ/p-
5bd8253082acdd181d02fa1b/7cdfbcc3/cr/s/q.jpg',
'
//imgcps.jd.com/ling4/100015163119/5Lqs6YCJ5aW96LSn/5L2g5YC85b6X5oul5pyJ/p-
5bd8253082acdd181d02fa17/0b842d03/cr/s/q.jpg',
'
//img20.360buyimg.com/pop/s1180x940_jfs/t1/192114/40/14091/51151/60f7cb1cE9e06
14db/511192a85bddd648.jpg.webp',
'
//imgcps.jd.com/ling4/100034738701/5Lqs6YCJ5aW96LSn/5L2g5YC85b6X5oul5pyJ/p-
5bd8253082acdd181d02f9d0/049bd553/cr/s/q.jpg'
]
var img = document.querySelector('.show>img')
//定时器控制对应的img的src路径变化
var index = 0 //记录是哪张图片
setInterval(()=>{
if(index>=imgs.length){
index = 0
}
img.src = imgs[index]
index++
},1000)
</script>
无缝轮播
保证第一张和最后一张之间没有缝隙
给最后一张后面添加一个第一张 (那么我们就有最后一张向第一张切换的过程)
当最后一张切换到第一张完成以后 需要将对应的定位变成第一张的位置
<script>
//获取对应的ul这个元素
var ul = document.querySelector('.content')
//获取对应的显示的盒子的大小
var show = document.querySelector('.show')
var width = show.clientWidth
//记录初始的个数
var size = ul.children.length
//在最后一张后面添加一个第一张
ul.appendChild(ul.firstElementChild.cloneNode(true))
//声明index记录对应的图片位置
var index = 0
setInterval(() => {
index++
//切换位置
bufferAnimation(ul, {
left: -1 * index * width
}, () => {
//到达最后一张变为0
if (index >= size) {
index = 0
//对应的位置要变成第一张的位置
ul.style.left = '0px'
}
})
},2000)
</script>