运动(动画)
概述:
运动(动画),操作对应的dom元素发生变化(这个变化要持续多次(修改样式)),每次间隔的时间是你肉眼察觉不出的(时间比较短)。当到达目标位置就停止。这个就是所谓的动画。
主要实现原理
-
利用定时器定时操作dom的样式
-
当对应的设置目标值到达以后清除对应的定时器
运动三大要素
-
当前值(current)
-
-
目标值 (target)
主要动画
匀速运动(每次变化的值是一样的)
示例(操作div的宽度变化)
// 操作div的宽度变化
//匀速运动每次变化的值是固定的
//获取div
var div = document.querySelector('div')
//当前值 通过获取当前的样式来获取对应的宽度
var current = parseFloat(getStyle(div).width)
//变化值
var step = 10
//目标值
var target = 500
//点击div 匀速变化他的宽度
div.onclick = function () {
var timer = setInterval(()=>{
//每次将当前值去加上变化量 完成变化
current += step
//设置给对应的div
div.style.width = current + 'px'
//到达目标位置清除定时器
if(current == target){
clearInterval(timer)
}
},40)
}
//封装一个方法获取对应的样式(获取所有的样式)
function getStyle(element){
if(window.getComputedStyle){
return window.getComputedStyle(element,'')
}else{
return element.currentStyle
}
}
封装的匀速运动代码(如果设置值不一样那么动画将不会一起完成)
//匀速运动的方法
//element表示移动的元素 target 目标位置{width:100,left:500}
function uniformVelocityAnimation(element, targetObj) {
//遍历target得到他的样式
for (let key in targetObj) {//key是字符串
//获取移动的目标样式的值
let current = parseFloat(getStyle(element)[key])
//得到目标值
let target = targetObj[key]
//步长设置 如果目标值是小于我们当前的值那么对应变化的量为负值 如果目标值大于我们当前值那么变化量为正值
let step = target>current?10:-10
//定时更改
let timer = setInterval(() => {
//判断是否到达目标位置
if (current >= target) {
clearInterval(timer)
} else {
//每次将对应的left值更改
current += step
//重新设置div的left值
element.style[key] = current + 'px'
}
}, 40)
}
}
//封装一个方法获取对应的样式(获取所有的样式)
function getStyle(element){
if(window.getComputedStyle){
return window.getComputedStyle(element,'')
}else{
return element.currentStyle
}
}
缓冲运动 (每次变化的值是越来越小的)
示例 (操作div的位置变化)
//div位置变化 以缓冲运动进行变化 //获取div var div = document.querySelector('div') //运动三要素 //当前值 let current = parseFloat(getStyle(div).left) //目標值 let target = 500 //给div添加点击事件 div.onclick = function () { var timer = setInterval(() => { //如果到了就清除定时器 if (current >= target) { clearInterval(timer) } else { //变化值 (目标值-当前值)/10 因为每次的值都会除10 那么对应的小数就会无限增加 就会导致永远到不了(取整) let step = Math.ceil((target - current) / 10) //控制current的变化 current += step //设置给对应的div div.style.left = current + 'px' } }, 40) } //封装一个方法获取对应的样式(获取所有的样式) function getStyle(element) { if (window.getComputedStyle) { return window.getComputedStyle(element, '') } else { return element.currentStyle } }
缓冲封装
//缓冲运动封装 //element表示当前的元素 target表示目标对象 function bufferAnimation(element, targetObj) { //如果element为undefined就直接报错 if(!element){ throw new Error('元素不能缺少') } //给元素对象添加一个属性为timer他是一个定时器 element.timer = setInterval(() => { var flag = true //遍历对象 for (let key in targetObj) { //取出当前值 let current = parseFloat(getStyle(element)[key]) //取出目标值 let target = targetObj[key] //判断当前如果是位置的变化及对应的宽度高度的变化 if(key=='width' || key == 'height' || key == 'left' || key == 'top'){ //步长 负值向下取整 正值向上取整 var step = target-current>0?Math.ceil((target - current) / 10):Math.floor((target - current) / 10) current += step element.style[key] = current + 'px' } //如果是透明度的变化 if(key == 'opacity'){ //步长 负值向下取整 正值向上取整 var step = target-current>0?Math.ceil((target - current) * 1000 / 10):Math.floor((target - current)*1000 / 10) current += step / 1000 element.style[key] = current } //如果是层高直接赋值 if(key == 'zIndex'){ element.style[key] = target } //如果没有完成就是false if(current != target){ flag = false } } //如果全部走完了就清除 if(flag){ clearInterval(element.timer) } },80) } //封装一个方法获取对应的样式(获取所有的样式) function getStyle(element) { if (window.getComputedStyle) { return window.getComputedStyle(element, '') } else { return element.currentStyle } }
链式动画
动画执行完接另一个动画不断进行链接。
封装进行(通过传入回调函数完成链式运动)
//缓冲运动封装 //element表示当前的元素 target表示目标对象 callbackFn表示传入的回调函数 function bufferAnimation(element, targetObj,callbackFn) { //如果element为undefined就直接报错 if(!element){ throw new Error('元素不能缺少') } //给元素对象添加一个属性为timer他是一个定时器 element.timer = setInterval(() => { var flag = true //遍历对象 for (let key in targetObj) { //取出当前值 let current = parseFloat(getStyle(element)[key]) //取出目标值 let target = targetObj[key] //判断当前如果是位置的变化及对应的宽度高度的变化 if(key=='width' || key == 'height' || key == 'left' || key == 'top'){ //步长 负值向下取整 正值向上取整 var step = target-current>0?Math.ceil((target - current) / 10):Math.floor((target - current) / 10) current += step element.style[key] = current + 'px' } //如果是透明度的变化 if(key == 'opacity'){ //步长 负值向下取整 正值向上取整 var step = target-current>0?Math.ceil((target - current) * 1000 / 10):Math.floor((target - current)*1000 / 10) current += step / 1000 element.style[key] = current } //如果是层高直接赋值 if(key == 'zIndex'){ element.style[key] = target } //如果没有完成就是false if(current != target){ flag = false } } //如果全部走完了就清除 if(flag){ clearInterval(element.timer) //调用回调函数 如果传入的参数是函数 if(typeof callbackFn == 'function'){ callbackFn() } } },20) }
示例(先变化div的宽度和高度 再变化他的位置)
<div></div>
<button></button>
<script src="./move.js"></script>
<script>
//先让div宽度和高度变化 再改变他的位置
//获取div
var div = document.querySelector('div')
document.querySelector('button').onclick = function () {
//调用缓冲动画 (俩个异步操作 你不知道对应的异步什么时候走完)
//可以进行二次封装 通过回调函数来解决异步的问题 (使异步变同步代码)
bufferAnimation(div, {
width: 200,
height: 300
}, () => {
//变化位置
bufferAnimation(div, {
left: 500
}, () => {
//变化位置
bufferAnimation(div, {
left: 100
})
})
})
}
</script>
轮播图
核心
-
对应图的切换
-
滚动切换 (更改的是对应大盒子的位置)
-
透明度切换 (更改的时候对应图片的透明度)
-
简单图片切换 (直接变化对应的图片)
滚动切换
-
对应大盒子里面容纳多个图片
-
图片的大小和显示盒子的大小一致
-
对应的大盒子的大小超出了对应的显示盒子(溢出隐藏)
-
根据对应的切换的下标来控制对应的大盒子的位置
<!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>
*{
margin: 0;
padding: 0;
}
.showBox,li{
width: 400px;
height: 250px;
}
li>img{
width: 100%;
}
.showBox{
margin: 200px auto;
/* 溢出隐藏 */
/* overflow: hidden; */
}
ul{
width: 700%;
position: relative;
}
ul>li{
list-style: none;
float: left;
}
</style>
</head>
<body>
<div class="showBox">
<ul class="wrap">
<li><img src="./images/slidepic1.jpg" alt=""></li>
<li><img src="./images/slidepic2.jpg" alt=""></li>
<li><img src="./images/slidepic3.jpg" alt=""></li>
<li><img src="./images/slidepic4.jpg" alt=""></li>
<li><img src="./images/slidepic5.jpg" alt=""></li>
<li><img src="./images/slidepic6.jpg" alt=""></li>
<li><img src="./images/slidepic7.jpg" alt=""></li>
</ul>
</div>
<script src="./move.js"></script>
<script>
//获取显示盒子
var showBox = document.querySelector('.showBox')
//获取显示盒子的宽度
var showWidth = parseFloat(getStyle(showBox).width)
//获取ul(需要切换位置的容器)
var wrap = document.querySelector('.wrap')
//封装一个autoMove的函数
function autoMove(){
//切换图片的定时器
var i = 0
var timer = setInterval(()=>{
i++ //这个i就是控制对应的位置的下标
//到达最后 切换到第一个
if(i==wrap.children.length){
i = 0
}
//移动对应的ul 0 -400 -800
//距离等于 当前下标*对应显示盒子的宽度*-1
var distance = i * showWidth * -1
bufferAnimation(wrap,{left:distance})
},2000)
}
//调用自动移动的方法
autoMove()
</script>
</body>
</html>