概述:运动主要是动画的操作,主要是操作某个document元素的属性变化(位置变化)
运动主要的三步骤
-
使用定时器来定时更改对应的内容
-
实时获取对应的元素的属性及相关内容
-
判断是否到达目标位置(到达后清除定时器)
匀速运动
概述:匀速运动的本质就是每次变化值都是同一个
示例
<!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>
div{
position: relative;
width: 100px;
height: 100px;
background-color: red;
}
</style>
</head>
<body>
<button>匀速运动</button>
<div></div>
<script>
//获取div
var btn = document.querySelector('button')
var div = document.querySelector('div')
btn.onclick = ()=>{
//使用定时器
var step = 10
var target = 500
var current = 0
var timer = setInterval(() => {
//在定时器内控制div的位置变化
current += step //当前位置变化
div.style.left = current + 'px' //设置位置
//当到达目标位置清除定时器
if(current == target){
clearInterval(timer)
}
}, 20);
}
</script>
</body>
</html>
概述: 缓冲运动的本质就是每次变化的值越来越小
示例
//缓冲运动 //获取div和对应的按钮 var btns = document.querySelectorAll('button') var box = document.querySelector('div') btns[0].onclick = ()=>{ //获取当前位置 var current = parseInt(getStyle(box,'left')) //定义步长和对应的目标位置 var step = 10 //初始步长 var target = 500 //目标位置 //定时器 var timer = setInterval(() => { //控制步长的变化 离目标会越来越小 把步长和这个距离绑定 step = (target - current)/20 > 0 ? Math.ceil((target - current)/20) : Math.floor((target - current)/20) //控制当前位置的变化 current += step //给当前位置赋值 box.style.left = current + 'px' //到达目标位置清除定时器 if(current == target){ clearInterval(timer) } }, 80); }
匀速移动和缓冲移动的封装
//获取样式的方法 function getStyle(ele, attr) { return window.getComputedStyle ? window.getComputedStyle(ele, null)[attr] : ele.currentStyle[attr] } //缓冲动画为true 不传就是匀速 function move(ele, target, isBuffer) { //获取当前位置 var current = parseInt(getStyle(ele, 'left')) //定义步长和对应的目标位置 var step = target - current > 0 ? 10 : -10 //定时器 var timer = setInterval(() => { if (isBuffer) { //控制步长的变化 离目标会越来越小 把步长和这个距离绑定 step = (target - current) / 20 > 0 ? Math.ceil((target - current) / 20) : Math.floor((target - current) / 20) } //控制当前位置的变化 current += step //给当前位置赋值 ele.style.left = current + 'px' //到达目标位置清除定时器 if (current == target) { clearInterval(timer) } }, 20) }
透明度变化
//透明度变化 function opacityAction(box,target){ //获取当前的透明度 //设置步长及对应的目标位置 var step var current = parseFloat(getStyle(box, 'opacity')) //开启定时器 var timer = setInterval(() => { // step = target-current>0?0.1:-0.1 //当透明度到达目标位置清除定时器 if(Math.abs(target-current) <= step){ clearInterval(timer) } // 最小值 0.01 step = (target-current)*100/10 > 0 ? Math.ceil((target-current)*100/10)/100 : Math.floor((target-current)*100/10)/100 //控制透明度的变化 current += step box.style.opacity = current }, 20); }
宽度变化
//获取按钮及div var box = document.querySelector('div') var btn = document.querySelector('button') btn.onclick = ()=>{ //获取开始的宽度 以及步长 var current = parseFloat(getStyle(box,'width')) var step var target = 500 //设置目标位置 var timer = setInterval(() => { //判断是否到达目标位置 if(Math.abs(target-current) <= step){ clearInterval(timer) } //设置步长 // step = target - current > 0 ? 10 : -10 step = (target-current )/10 > 0 ? Math.ceil((target-current)/10) : Math.floor((target-current)/10) //设置当前的位置 current += step box.style.width = current + 'px' }, 20); } //获取样式的方法 function getStyle(ele, attr) { return window.getComputedStyle ? window.getComputedStyle(ele, null)[attr] : ele.currentStyle[attr] }
简易封装move.js
//获取样式的方法 function getStyle(ele, attr) { return window.getComputedStyle ? window.getComputedStyle(ele, null)[attr] : ele.currentStyle[attr] } //缓冲动画为true 不传就是匀速 function move(ele, target, isBuffer = false) { clearInterval(ele.timer) //清除之前的定时器影响 //针对于px为单位的 width,height,left,top //opacity不需要px //zIndex不需要动画 //获取target对象里面的所有的key ele.timer = setInterval(() => { var flag = true for (let key in target) { //获取当前位置 var current = parseFloat(getStyle(ele, key)) ? parseFloat(getStyle(ele, key)) : 0 //定义步长和对应的目标位置 if(key == 'opacity'){ var step = target[key] - current > 0 ? 0.01 : -0.01 }else{ var step = target[key] - current > 0 ? 10 : -10 } //定时器 if (key == 'zIndex') { //层级 ele.style[key] = target[key] //直接设置 } else { //没有到达设置为false if (Math.abs(target[key] - current ) > step) { flag = false } if (isBuffer) { //如果是缓冲的 if (key == 'opacity') { //透明度 // 最小值 0.01 step = (target[key] - current) * 100 / 10 > 0 ? Math.ceil((target[key] - current) * 100 / 10) / 100 : Math.floor((target[key] - current) * 100 / 10) / 100 } else { //其他的 //控制步长的变化 离目标会越来越小 把步长和这个距离绑定 step = (target[key] - current) / 10 > 0 ? Math.ceil((target[key] - current) / 10) : Math.floor((target[key] - current) / 10) } } //控制当前位置的变化 current += step //给当前位置赋值 if (key != 'opacity') { ele.style[key] = current + 'px' } else { ele.style[key] = current } } } if (flag) { clearInterval(ele.timer) } }, 20) }
链式动画
链式动画 等一个完成以后再进行某个操作 (通过回调函数来实现)
//获取样式的方法 function getStyle(ele, attr) { return window.getComputedStyle ? window.getComputedStyle(ele, null)[attr] : ele.currentStyle[attr] } //缓冲动画为true 不传就是匀速 function move(ele, target, isBuffer = true,callback) { clearInterval(ele.timer) //清除之前的定时器影响 //针对于px为单位的 width,height,left,top //opacity不需要px //zIndex不需要动画 //获取target对象里面的所有的key ele.timer = setInterval(() => { var flag = true for (let key in target) { //获取当前位置 var current = parseFloat(getStyle(ele, key)) ? parseFloat(getStyle(ele, key)) : 0 //定义步长和对应的目标位置 if(key == 'opacity'){ var step = target[key] - current > 0 ? 0.01 : -0.01 }else{ var step = target[key] - current > 0 ? 10 : -10 } //定时器 if (key == 'zIndex') { //层级 ele.style[key] = target[key] //直接设置 } else { //没有到达设置为false if (Math.abs(target[key] - current ) > step) { flag = false } if (isBuffer) { //如果是缓冲的 if (key == 'opacity') { //透明度 // 最小值 0.01 step = (target[key] - current) * 100 / 10 > 0 ? Math.ceil((target[key] - current) * 100 / 10) / 100 : Math.floor((target[key] - current) * 100 / 10) / 100 } else { //其他的 //控制步长的变化 离目标会越来越小 把步长和这个距离绑定 step = (target[key] - current) / 10 > 0 ? Math.ceil((target[key] - current) / 10) : Math.floor((target[key] - current) / 10) } } //控制当前位置的变化 current += step //给当前位置赋值 if (key != 'opacity') { ele.style[key] = current + 'px' } else { ele.style[key] = current } } } if (flag) { clearInterval(ele.timer) //如果你的回调是一个函数就执行 if(callback instanceof Function){ callback() } } }, 20) }
回到顶部的实现
<!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>
div{
height: 1500px;
}
button{
display: none;
position: fixed;
bottom: 50px;
right: 30px;
}
</style>
</head>
<body>
<div></div>
<button>回到顶部</button>
<script src="./move.plus.js"></script>
<script>
//滚动栏 监听滚动栏滚动
var btn = document.querySelector('button')
window.onscroll = function(){
if(window.scrollY >= 500){
btn.style.display = 'block'
move(btn,{opacity:1})
}else{
move(btn,{opacity:0})
}
}
btn.onclick = function(){
//将对应的滚动栏 以缓冲动画运动到对应的位置0
var target = 0
var current = window.scrollY
var step = (target - current)/10 > 0 ? Math.ceil((target - current)/10) : Math.floor((target - current)/10)
var timer = setInterval(() => {
current += step
window.scrollTo(0,current)
if(current == target){
clearInterval(timer)
}
}, 20);
}
</script>
</body>
</html>
第三方 move.js
主要使用
to 从当前位置到达某个位置(x,y)
set 设置相关样式 (样式名,样式值)
end 结束当前动画
duration 运动的时长(默认时长为0.5s)
<!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;
}
</style>
</head>
<body>
<div class="box"></div>
<script src="./move.min.js"></script>
<script>
move('.box')
.to(500, 200) //到某个位置 to到某个位置 set 设置相关样式 then回调 end 表示结束 duration 总时长
// .rotate(180)
// .scale(.5)
.set('background-color', '#888')
.set('border-color', 'black')
.duration('2s')
// .skew(50, -10)
// .then()//回调
// .set('opacity', 0)
// .duration('0.3s')
// .scale(0.1)
// .pop()
.end();
</script>
</body>
</html>
swiper插件(内置css和js)
概述:swiper是一个开源的免费的一个滚动的组件(他可以运用于轮播图 焦点图 滑动效果等)
-
-
他里面包含对应的css (以class的形式)
-
包含对应的js文件 js进行操作(面向对象形式进行封装)
swiper的版本很多(从2.0 到 8.0常用的)
5.0 版本
html主体
<!-- class swiper-container 主体内容 --> <div class="swiper-container"> <!-- 表示当前的轮播 --> <div class="swiper-wrapper"> <!-- swiper-slide表示一个个的图 --> <div class="swiper-slide">Slide 1</div> <div class="swiper-slide">Slide 2</div> <div class="swiper-slide">Slide 3</div> <div class="swiper-slide">Slide 4</div> <div class="swiper-slide">Slide 5</div> <div class="swiper-slide">Slide 6</div> <div class="swiper-slide">Slide 7</div> <div class="swiper-slide">Slide 8</div> <div class="swiper-slide">Slide 9</div> <div class="swiper-slide">Slide 10</div> </div> <!-- 分页器 下面的点 --> <div class="swiper-pagination"></div> <!-- 左右切换的箭头 --> <div class="swiper-button-next"></div> <div class="swiper-button-prev"></div> </div>
js主体
//传入选择器 及相关配置 new Swiper('.swiper-container', { // autoplay:{ // delay: 3000, // stopOnLastSlide: true, //移上对应的块 是否停止的动画 // disableOnInteraction: true,//禁用迭代 // } autoplay: true, //开启自动播放 所有的全部使用默认值 pagination: { //分页器 el: '.swiper-pagination', //分页的点生成在哪 }, navigation: {//导航按钮 nextEl: '.swiper-button-next', prevEl: '.swiper-button-prev', }, })
move.js 文件
//获取样式的方法 function getStyle(ele, attr) { return window.getComputedStyle ? window.getComputedStyle(ele, null)[attr] : ele.currentStyle[attr] } //缓冲动画为true function move(ele, target, isBuffer = true,callback) { clearInterval(ele.timer) //清除之前的定时器影响 //针对于px为单位的 width,height,left,top //opacity不需要px //zIndex不需要动画 //获取target对象里面的所有的key ele.timer = setInterval(() => { var flag = true for (let key in target) { //获取当前位置 var current = parseFloat(getStyle(ele, key)) ? parseFloat(getStyle(ele, key)) : 0 //定义步长和对应的目标位置 if(key == 'opacity'){ var step = target[key] - current > 0 ? 0.01 : -0.01 }else{ var step = target[key] - current > 0 ? 10 : -10 } //定时器 if (key == 'zIndex') { //层级 ele.style[key] = target[key] //直接设置 } else { if (isBuffer) { //如果是缓冲的 if (key == 'opacity') { //透明度 // 最小值 0.01 step = (target[key] - current) * 100 / 10 > 0 ? Math.ceil((target[key] - current) * 100 / 10) / 100 : Math.floor((target[key] - current) * 100 / 10) / 100 } else { //其他的 //控制步长的变化 离目标会越来越小 把步长和这个距离绑定 step = (target[key] - current) / 10 > 0 ? Math.ceil((target[key] - current) / 10) : Math.floor((target[key] - current) / 10) } } //没有到达设置为false if (Math.abs(target[key] - current ) > Math.abs(step)) { flag = false } //控制当前位置的变化 current += step //给当前位置赋值 if (key != 'opacity') { ele.style[key] = current + 'px' } else { ele.style[key] = current } } } if (flag) { console.log(123); clearInterval(ele.timer) //如果你的回调是一个函数就执行 if(callback instanceof Function){ callback() } } }, 20) }
面向对象的轮播
class Rotation { constructor(element) { this.banner = element.querySelector('.banner') this.length = this.banner.children.length this.element = element this.prevBtn = element.querySelector('.prev') this.nextBtn = element.querySelector('.next') this.focusList = this.init() this.index = 0 this.autoMove() //调用对应的事件监听 this.handlerChange() this.handlerFocusClick() this.handlerMouseBox() } init() { let ol = document.createElement('ol') //根据对应的个数生成 for (var i = 0; i < this.length; i++) { if (i == 0) { ol.innerHTML += `<li class="selected"></li>` } else { ol.innerHTML += `<li></li>` } } //添加进去 this.element.appendChild(ol) //给ul的后面再添加第一个li //克隆第一个 var clone = this.banner.children[0].cloneNode(true) this.banner.appendChild(clone) //返回所有添加的li return ol.children } changePosition(isRight = true) { if (isRight) { this.index++ if (this.index == this.banner.children.length) { //强行设置对应的为第一个 this.banner.style.left = '0px' //控制对应的下标为0 this.index = 0 } } else { this.index-- //如果到第一个应该切到最后一个 if (this.index == -1) { //强行设置对应的最后一个 this.banner.style.left = this.length * -1 * this.element.clientWidth + 'px' this.index = this.length - 1 } } this.setFocus(this.index) // move('.banner').set('left', -1*liWidth * index + 'px').end() // move('.banner').to(-liWidth * index, 0).end() move(this.banner, { left: -1 * (this.element.clientWidth) * this.index }, true) } autoMove() { this.timer = setInterval(() => { this.changePosition() }, 2000); } setFocus(i) { //超出范围等于0 if (i > this.length - 1) { i = 0 } //小于0 等于最大下标 if (i < 0) { i = this.length - 1 } //排他 //先把所有的全部清除 再给自己设置 // 获取所有的ol里面的li Array.from(this.focusList).forEach((li) => { li.className = '' }) this.focusList[i].className = 'selected' } //焦点点击事件 handlerFocusClick() { //事件委托机制 this.focusList[0].parentElement.onclick = (e) => { e = e || window.event clearInterval(this.timer) if (e.target.nodeName == 'LI') { var i = Array.from(this.focusList).findIndex((li) => { return li == e.target }) //移动到对应的位置 move(this.banner, { left: -this.element.clientWidth * i }, true) //将i赋值给index this.index = i //切焦点 this.setFocus(i) // this.autoMove() 导致多一个定时器无法清除 } } } //移动动盒子上面 handlerMouseBox() { this.banner.parentElement.onmouseenter = () => { //控制俩个div显示 this.nextBtn.style.display = 'block' this.prevBtn.style.display = 'block' //清除动画 clearInterval(this.timer) } this.banner.parentElement.onmouseleave = () => { //控制俩个div隐藏 this.nextBtn.style.display = 'none' this.prevBtn.style.display = 'none' //开始动画 this.autoMove() } } //左右切换处理 handlerChange() { //左边的事件 this.prevBtn.onclick = () => { this.changePosition(false) } //右边的事件 this.nextBtn.onclick = () => { this.changePosition() } } } //调用 var box = document.querySelector('.box') new Rotation(box)
放大镜
class Magnifier { constructor(smallBox, bigBox) { this.smallBox = smallBox this.bigBox = bigBox this.move = smallBox.querySelector('.move') this.bigImg = bigBox.children[0] this.init() this.handlerMouse() } init() { //计算对应的move这个盒子的宽高 // 大的比大的等于小的比小的 bigImg/bigBox = box/move ==> bigImg/box == bigBox/move this.move.style.width = this.smallBox.clientWidth / (this.bigImg.clientWidth / this.bigBox .clientWidth) + 'px' this.move.style.height = this.smallBox.clientHeight / (this.bigImg.clientHeight / this.bigBox .clientHeight) + 'px' //先需要隐藏 this.move.style.display = 'none' this.bigBox.style.display = 'none' } handlerMouse() { //移入移出 this.smallBox.onmouseenter = () => { this.move.style.display = 'block' this.bigBox.style.display = 'block' } this.smallBox.onmouseleave = () => { this.move.style.display = 'none' this.bigBox.style.display = 'none' } //移动 this.smallBox.onmousemove = ({ pageX, pageY }) => { //获取鼠标在smallbox里面位置 let currentX = pageX - this.smallBox.offsetLeft let currentY = pageY - this.smallBox.offsetTop //中心点位置 let centerPoint = { x: this.smallBox.clientWidth / 2, y: this.smallBox.clientHeight / 2 } //移动的位置 let targetPoint = { x: currentX - centerPoint.x, y: currentY - centerPoint.y } //边界判断 if(targetPoint.x<0){ targetPoint.x = 0 } if(targetPoint.y<0){ targetPoint.y = 0 } //最大值判断 let maxPoint = { x: this.smallBox.clientWidth - this.move.offsetWidth, y: this.smallBox.clientHeight - this.move.offsetHeight } if(targetPoint.x > maxPoint.x){ targetPoint.x = maxPoint.x } if(targetPoint.y > maxPoint.y){ targetPoint.y = maxPoint.y } //设置对应的位置 this.move.style.left = targetPoint.x + 'px' this.move.style.top = targetPoint.y + 'px' //还要设置大盒子里面图片的位置 this.bigImg.style.left = -targetPoint.x * this.bigImg.clientWidth / this.smallBox.clientWidth + 'px' this.bigImg.style.top = -targetPoint.y * this.bigImg.clientHeight / this.smallBox.clientHeight + 'px' } } } var small = document.querySelector('.box') var big = document.querySelector('.bigbox') new Magnifier(small, big)
浙公网安备 33010602011771号