运动(动画)
概述:
运动(动画),操作对应的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>