-
匀速运动:在相同的时间内 移动的距离一样
let box=document.querySelector("#box"); let left=0; let timer=setInterval(function(){ left+=13; if(left>=1000){ left=1000; clearInterval(timer); } box.style.left=left+"px"; },50);
-
加速运动:在相同的时间内 移动的距离 越来越长,速度越来越快
let box = document.querySelector("#box"); let left = 0; let speed = 10; let timer = setInterval(function () { left += speed; speed += 5; if (left >= 1000) { left = 1000; clearInterval(timer); } console.log(left); box.style.left = left + "px"; }, 100);
-
减速运动:在相同的时间内 移动的巨鹿越来越短 速度越来越小
let box = document.querySelector("#box"); let left = 0; let speed = 80; let timer = setInterval(function () { speed -= 5; // 当速度为0的时候 就停止运动 if (speed <= 0) { clearInterval(timer); speed = 0; } left += speed; box.style.left = left + "px"; }, 100);
-
缓冲运动:在固定的距离中 做减速运动
let box = document.querySelector("#box1");
// let left = 0;
let target = 1000;
// 移动到 left = 1000的时候停止运动
// 减速运动
let speed;
let timer = setInterval(function () {
// 获取元素当前的left
let left = parseInt(getStyle(box, "left"));
// 最开始的left = 0 target = 1000
// speed =( target - left)/10 = 100
speed = Math.ceil((target - left) / 10);
// 速度:0.3 ==>1
// left = 999
// 1000 - 999 = 1/10=0.1
// speed = 0.1
// left += 0.1==>999+0.1==999.1
left += speed;
if (left == target) {
clearInterval(timer);
}
box.style.left = left + "px";
}, 100);
封装一个运动函数
<!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>
#box {
width: 100px;
height: 100px;
background: pink;
position: absolute;
top: 0px;
left: 0px;
}
button {
position: fixed;
right: 0px;
}
</style>
<script src="./utils.js"></script>
</head>
<body>
<div id="box"></div>
<button id="btn">点击</button>
<script>
/*
函数的需要的参数:在代码中是可变的
动画的对象 ele
参与动画的属性 attr
动画的目标值 target
*/
let btn = document.querySelector("#btn");
let box = document.querySelector("#box");
// let timer;
btn.onclick = function () {
// 点击的时候 才去执行动画的时候
// 当多次点击的时候 肯定会开启多定时器来执行这个动画
// 不管点击多少次 ,始终保持一个定时器执行这个动画
move(box, "height", 500);
// move(box,{height:500,width:500})
};
// 思考 同时改变 宽度 和高度(同时执行两个以上的动画)
// 一个属性有一个目标值
// 多个属性的时候 可以以对象的形式传递参数
function move(ele, attr, target) {
let speed;
// 在开启定时器之前 把已经存在的定时器 清除
clearInterval(ele.timer);
// 把定时器 添加到 dom对象中
ele.timer = setInterval(function () {
let left = parseInt(getStyle(ele, attr));
speed = Math.ceil((target - left) / 10);
left += speed;
if (left == target) {
clearInterval(ele.timer);
}
ele.style[attr] = left + "px";
}, 50);
}
</script>
</body>
</html>
动画函数的优化
<!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>
#box {
width: 100px;
height: 100px;
background: pink;
position: absolute;
top: 0px;
left: 0px;
}
button {
position: fixed;
right: 0px;
}
</style>
<script src="./utils.js"></script>
</head>
<body>
<div id="box"></div>
<button id="btn">点击</button>
<script>
/*
函数的需要的参数:在代码中是可变的
动画的对象 ele
参与动画的属性 attr
动画的目标值 target
*/
let btn = document.querySelector("#btn");
let box = document.querySelector("#box");
btn.onclick = function () {
// move(box, "height", 500);
move(box, { height: 500, width: 800 }, function () {
// console.log('动画已经执行完成 ,我是回调函数');
box.style.background = "orange";
});
};
// 思考 同时改变 宽度 和高度(同时执行两个以上的动画)
// 一个属性有一个目标值
// 多个属性的时候 可以以对象的形式传递参数
function move(ele, obj, callback) {
let index = 0; // 记录定时器的个数(记录动画的个数)
for (let attr in obj) {
index++;
// 在开启定时器之前 把已经存在的定时器 清除
clearInterval(ele[attr]);
// 把定时器 添加到 dom对象中
// ele.width
// ele.height
ele[attr] = setInterval(function () {
let left = parseInt(getStyle(ele, attr));
let speed = Math.ceil((obj[attr] - left) / 10);
left += speed;
ele.style[attr] = left + "px";
if (left == obj[attr]) {
clearInterval(ele[attr]);
// 动画结束,只有两个动画都执行完成 才表示这个动画结束
// 没清除一个定时器的时候 就index--
index--;
if (index == 0) {
// 当动画执行完成时候 执行回调函数
// 不一定每一次都会有回调函数
// 没有回调函数的时候 就不执行callback
// 短路运算符:当callback存在的时候 才会执行 callback()
callback && callback();
}
}
}, 50);
}
}
</script>
</body>
</html>
动画函数升级版
<!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>
.box{
width: 500px;height: 500px;
background: pink;
}
</style>
<script src="./utils.js"></script>
</head>
<body>
<div class="box"></div>
<script>
let box = document.querySelector('.box');
box.onmouseover = function(){
move(box,{width:100,height:100},function(){
console.log(1);
})
}
</script>
</body>
</html>
透明度的动画效果
<!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>
.box {
width: 200px;
height: 200px;
background: red;
opacity: 0.8;
}
</style>
<script src="./utils.js"></script>
</head>
<body>
<div class="box"></div>
<script>
let box = document.querySelector(".box");
box.onmouseover = function () {
// box.style.opacity = "0.3";
// 透明度的取值只能取0-1
// 0-1 改变为 0-100
// move(box,{opacity:25})
move(box, { width: 500, opacity: 25 });
};
</script>
</body>
</html>
轮播图的结构
<!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>
* {
padding: 0;
margin: 0;
}
ul,
li {
list-style: none;
}
.box {
width: 500px;
height: 300px;
border: 1px solid #ccc;
overflow: hidden;
position: absolute;
left: 0px;
top: 0px;
right: 0px;
bottom: 0px;
margin: auto;
}
.box ul {
width: 3000px;
height: 300px;
position: absolute;
}
.box ul li {
width: 500px;
float: left;
height: 300px;
text-align: center;
line-height: 300px;
font-size: 50px;
}
.box ol {
position: absolute;
bottom: 20px;
right: 20px;
}
.box ol li {
float: left;
width: 20px;
height: 20px;
background: #58bc58;
border-radius: 50%;
text-align: center;
line-height: 20px;
font-size: 12px;
margin-right: 5px;
cursor: pointer;
user-select: none;
color: #fff;
}
.box ol .active {
background: blue;
}
.box .btn {
position: absolute;
height: 40px;
width: 100%;
top: 50%;
transform: translateY(-50%);
}
.box .btn .leftBtn {
float: left;
height: 40px;
width: 60px;
font-size: 50px;
text-align: center;
line-height: 40px;
color: #fff;
cursor: pointer;
user-select: none;
background: rgba(0, 0, 0, 0.336);
}
.box .btn .rightBtn {
float: right;
height: 40px;
width: 60px;
font-size: 50px;
text-align: center;
line-height: 40px;
color: #fff;
cursor: pointer;
user-select: none;
background: rgba(0, 0, 0, 0.336);
}
</style>
<script src="./utils.js"></script>
</head>
<body>
<div class="box">
<ul>
<li style="background: pink">li1</li>
<li style="background: orange">li2</li>
<li style="background: blueviolet">li3</li>
<li style="background: palevioletred">li4</li>
<li style="background: yellowgreen">li5</li>
<li style="background: skyblue">li6</li>
</ul>
<ol>
<!-- <li>1</li>
<li>2</li>
<li>3</li>
<li>4</li>
<li>5</li>
<li>6</li> -->
</ol>
<div class="btn">
<span class="leftBtn"><</span>
<span class="rightBtn">></span>
</div>
</div>
<script>
/*
【1】根据 ul中的li元素 来生成ol中li元素
【2】复制第一个轮播图 追加到 最后一个元素的后面
【3】改变 ul的宽度
【4】移动ul的left
【5】当移入box的时候 停止轮播图的切换
【6】当移出的是 轮播图继续轮播
【7】点击左右按钮的时候 切换轮播图
【9】点击 ol中的li元素的时候 切换到对应的图片
把点击的这个元素的索引 赋值给index
*/
// 获取元素
let box = document.querySelector(".box");
let ul = box.querySelector("ul");
let lis = ul.querySelectorAll("li");
let ol = box.querySelector("ol");
let leftBtn = box.querySelector(".leftBtn");
let rightBtn = box.querySelector(".rightBtn");
let flag = true; //表示可以点击
// 【1】根据 ul中的li元素 来生成ol中li元素
let str = "";
lis.forEach((item, index) => {
if (index == 0) {
str += `<li class="active">${index + 1}</li>`;
} else {
str += `<li>${index + 1}</li>`;
}
});
ol.innerHTML = str;
let btnLi = ol.querySelectorAll("li");
// 【2】复制第一个轮播图 追加到 最后一个元素的后面
let copyLi = lis[0].cloneNode(true);
ul.appendChild(copyLi);
// 【3】改变 ul的宽度(获取添加之后的li的个数 和li的宽度)
lis = ul.querySelectorAll("li");
let width = lis[0].offsetWidth;
ul.style.width = lis.length * width + "px";
// 【4】移动ul的left
// 需要定一个定时器不断的去执行 move函数
// 当存在定时器的嵌套的时候 一定保证 外面定时器的切换时间 大于 里面定时器执行的总时间
let index = 0;
let timer = setInterval(function () {
index++;
autoPlay();
}, 2000);
// 【5】当移入box的时候 停止轮播图的切换
box.onmouseover = function () {
clearInterval(timer);
};
// 【6】当鼠标移出的时候 继续轮播图的切换
box.onmouseout = function () {
timer = setInterval(function () {
index++;
autoPlay();
}, 2000);
};
// 【7】点击左边按钮
leftBtn.onclick = function () {
if (flag) {
flag = false;
// 如果index = 0的时候表示第一张图片
// 把index设置为 最后一章图片的索引,ul的left 瞬间移动到最后一张图片
if (index == 0) {
index = 6;
ul.style.left = index * -500 + "px";
}
index--;
autoPlay();
}
};
// 【8】点击右边的按钮
rightBtn.onclick = function () {
if (flag) {
console.log(1);
index++;
flag = false;
autoPlay();
}
};
// 把函数部分封装
function autoPlay() {
// index++;
for (let i = 0; i < btnLi.length; i++) {
btnLi[i].classList.remove("active");
}
// 当index=6的时候 显示的就是最后一张 内容就为第一张
if (index == 6) {
btnLi[0].classList.add("active");
} else {
btnLi[index].classList.add("active");
}
move(ul, { left: -500 * index }, function () {
// 动画结束之后 把flag改为true,表示可以继续点击
flag = true;
// 当index 移动到最后一张图片的时候 应该改变index = 0
// 并且ul 瞬间 移动left = 0的位置
if (index == 6) {
index = 0;
ul.style.left = 0 + "px";
}
});
}
</script>
</body>
</html>