引入运动函数
+ 就是把运动的这一段过程抽离出来, 封装成一个函数
需求1: 实现点击 div 移动到 200px 的位置
=> 需要运动
=> 需要一个 setInterval(), 每隔一段时间移动一段距离, 到达目标位置后关闭定时器
需求2: 实现点击 p 移动到 300px 的位置
*{
margin: 0;
padding: 0;
}
div{
width: 100px;
height: 100px;
background-color: #ccc;
position: absolute;
left: 0;
top: 0;
}
p{
width: 100px;
height: 100px;
background-color: pink;
position: absolute;
left: 0;
top: 110px;
}
<div></div>
<p></p>
var div = document.querySelector('div')
div.addEventListener('click', function(){
let distance = 0
let timer = setInterval(function(){
distance += 10
div.style.left = distance + 'px'
if(distance >= 200){
clearInterval(timer)
}
}, 30)
})
var p = document.querySelector('p')
p.addEventListener('click', function(){
let distance = 0
let timer = setInterval(function(){
distance += 10
p.style.left = distance + 'px'
if(distance >= 300){
clearInterval(timer)
}
}, 30)
})
运动函数第一版
需要一个函数, 接收三个参数
=> 元素
=> 属性
=> 目标位置
发现问题
+ 只能运动一个属性
function move(ele, type, target){
let distance = 0
let timer = setInterval(function(){
distance += 10
ele.style[type] = distance + 'px'
if(distance >= target){
clearInterval(timer)
}
}, 30)
}
var div = document.querySelector('div')
div.addEventListener('click', function(){
move(div, 'left', 200)
})
运动函数第二版
发现问题
+ 只能运动一个属性
解决问题
+ 以对象的形式把你要运动的属性传递进去
=> { left: 200, top: 300 }
+ 我的函数其实只接收 两个 参数就够了
=> 元素
=> 目标位置
发现问题
+ 当多个属性的目标值不一样的时候, 不能走出对角线
+ 当不从 0 开始的时候, 运动开始时会先回到 0 位置一次
var div = document.querySelector('div')
div.addEventListener('click', function(){
move(div, { left: 200, top: 300 })
})
function move(ele, target){
for(let key in target){
let distance = 0
let timer = setInterval(() => {
distance += 10
ele.style[key] = distance + 'px'
if(distance >= target[key]){
clearInterval(timer)
}
}, 30)
}
}
运动函数第三版
发现问题
1. 当多个属性的目标值不一样的时候, 不能走出对角线
2. 当不从 0 开始的时候, 运动开始时会先回到 0 位置一次
解决问题
1. 改变速度
=> 每 30ms 移动一次
=> 每次移动都移动剩余距离的 十分之一
2. 拿到元素的初始位置
=> 把 distance 默认设置为元素初始位置即可
发现问题
+ 我不一定从 整5倍数开始, 比如 101
+ 我的目标位置也可以是一个零散的数, 此时永远无法到达目标位置
+ 我不一定向正方向前进, 此时在运动一次后定时器便会关闭
+ 运动不了 opacity
var div = document.querySelector('div')
div.addEventListener('click', function(){
move(div, { left: 623, top: 598 })
})
function move(ele, target){
for(let key in target){
let distance = parseInt(getStyle(ele, key))
let timer = setInterval(() => {
distance += 10
ele.style[key] = distance + 'px'
if(distance >= target[key]){
clearInterval(timer)
}
}, 30)
}
}
function move(ele, target){
for(let key in target){
let current = parseInt(getStyle(ele, key))
let timer = setInterval(() => {
let distance += (target[key] - current) / 10
ele.style[key] = distance + 'px'
if(distance >= target[key]){
clearInterval(timer)
}
}, 30)
}
}
function move(ele, target){
for(let key in target){
let timer = setInterval(() => {
let current = parseInt(getStyle(ele, key))
let distance = (target[key] - current) / 10
distance = distance > 0 ? Math.ceil(distance): Math.floor(distance)
console.log(current, distance)
if(current === target[key]){
clearInterval(timer)
}else{
ele.style[key] = current + distance + 'px'
}
}, 30)
}
}
运动函数第四版
发现问题
+ 运动不了 opacity
解决问题
+ 拿到的时候放大 100 倍
+ 最后设置的时候再缩小 100 倍
发现问题
+ opacity 只能从 1 到 0
var div = document.querySelector('div')
div.addEventListener('click', function(){
move(div, { opacity: 0 })
})
function move(ele, target){
for(let key in target){
let timer = setInterval(() => {
let current = key === 'opacity' ? getStyle(ele, 'opacity') * 100 : parseInt(getStyle(ele, key))
let distance = (target[key] - current) / 10
distance = distance > 0 ? Math.ceil(distance): Math.floor(distance)
console.log(current, distance)
if(current === target[key]){
clearInterval(timer)
}else{
ele.style[key] = key === 'opacity' ? (current + distance) / 100 : current + distance + 'px'
}
}, 30)
}
}
opacity 只能从 1 到 0 的问题出现原因:
=> 若开始位置 current 为0.2 , 目标位置 target[key] 为1
=> current 放大 100 倍, 为 20, distance 为 (target[key] - current) / 10 = -1.9
=> 在做判断时, 进入赋值, ele.style[key] 就等于 (20 + (-1.9) ) / 100 = 0.181
=> 往 0 的方向走了
运动函数第五版
发现问题
+ opacity 只能从 1 到 0
+ 原因: target[key] 要么是 0, 要么是 1
解决问题
+ 当我准备运动的时候
+ 我判断一下, 如果你需要运动的有一个是 opacity
=> 我直接把 target 里面的值放大 100 倍
发现问题
+ 我没办法捕捉到运动的真正结束
+ 最后一个属性运动结束以后, 才是整个运动结束
var div = document.querySelector('div')
div.addEventListener('click', function(){
move(div, { opacity: 1 , left: 200, top: 300 })
})
function move(ele, target){
for(let key in target){
if(key === 'opacity') target[key] *= 100
let timer = setInterval(() => {
let current = key === 'opacity' ? getStyle(ele, 'opacity') * 100 : parseInt(getStyle(ele, key))
let distance = (target[key] - current) / 10
distance = distance > 0 ? Math.ceil(distance): Math.floor(distance)
console.log(current, distance)
if(current === target[key]){
clearInterval(timer)
}else{
ele.style[key] = key === 'opacity' ? (current + distance) / 100 : current + distance + 'px'
}
}, 30)
}
}
运动函数第六版
发现问题
+ 我没办法捕捉到运动的真正结束
+ 最后一个属性运动结束以后, 才是整个运动结束
解决问题
+ 计数器
=> 在哪定义
=> 在哪开启
=> 在哪关闭
发现问题
+ 我没有办法在运动结束再做点什么
+ 需求: 运动结束之后, 背景颜色变成 粉色
+ 需求: 运动结束之后, 把 display 变成 none
var div = document.querySelector('div')
div.addEventListener('click', function(){
move(div, { opacity: 1, left: 200, top: 300 })
})
function move(ele, target){
let count = 0
for(let key in target){
if(key === 'opacity') target[key] *= 100
count++
let timer = setInterval(() => {
let current = key === 'opacity' ? getStyle(ele, 'opacity') * 100 : parseInt(getStyle(ele, key))
let distance = (target[key] - current) / 10
distance = distance > 0 ? Math.ceil(distance): Math.floor(distance)
if(current === target[key]){
clearInterval(timer)
count--
if(!count){
ele.style.backgroundColor = 'pink'
}
}else{
ele.style[key] = key === 'opacity' ? (current + distance) / 100 : current + distance + 'px'
}
}, 30)
}
}
运动函数第七版
发现问题
+ 我没有办法在运动结束再做点什么
+ 需求: 运动结束之后, 背景颜色变成 粉色
+ 需求: 运动结束之后, 把 display 变成 none
解决问题:
+ 目的: 运动结束后做点事情
+ 思路:
1. 把我想做的事情放在一个 盒子里 (函数: 就是一个盒子, 承载一段代码, 在你需要的时候调用)
2. 把这个盒子传递给 move 函数
3. 在运动结束的时候, 你帮我把盒子里面的代码执行一下
+ 方法:
=> 第三个参数传递一个函数, 把我想要在运动结束做的事情传递进去
发现问题
+ 当调用函数不传函数参数时, 会报错
解决问题
方法1: fn && fn()
方法2: 参数默认值
var div = document.querySelector('div')
div.addEventListener('click', function(){
move(div, { opacity: 1, left: 200, top: 300 }, end)
function end(){
div.style.backgroundColor = 'purple'
}
})
var p = document.querySelector('p')
p.addEventListener('click', function(){
move(p, {width: 200, height: 200 }, function(){
p.style.display = 'none'
})
})
function move(ele, target, fn = () => {}){
let count = 0
for(let key in target){
if(key === 'opacity') target[key] *= 100
count++
let timer = setInterval(() => {
let current = key === 'opacity' ? getStyle(ele, 'opacity') * 100 : parseInt(getStyle(ele, key))
let distance = (target[key] - current) / 10
distance = distance > 0 ? Math.ceil(distance): Math.floor(distance)
if(current === target[key]){
clearInterval(timer)
count--
if(!count){
fn()
}
}else{
ele.style[key] = key === 'opacity' ? (current + distance) / 100 : current + distance + 'px'
}
}, 30)
}
}
简单版多属性运动函数的封装
function move(ele, target, fn = () => {}){
let count = 0
for(let key in target){
if(key === 'opacity') target[key] *= 100
count++
let timer = setInterval(() => {
let current = key === 'opacity' ? getStyle(ele, 'opacity') * 100 : parseInt(getStyle(ele, key))
let distance = (target[key] - current) / 10
distance = distance > 0 ? Math.ceil(distance): Math.floor(distance)
if(current === target[key]){
clearInterval(timer)
count--
if(!count) fn()
}else{
ele.style[key] = key === 'opacity' ? (current + distance) / 100 : current + distance + 'px'
}
}, 30)
}
}