1、含义: 封装一个函数让一个元素改变现有状态,将来想要让元素运动的时候直接调用这个函数就可以了;
2、原理:利用定时器setInterval()不断移动盒子位置
3、实现步骤
=>获取当前盒子的位置
=>让盒子在当前位置上加上一个需要移动距离
=>利用定时器不断重复这个操作
=>加一个定时器结束的条件
注意:此元素需要添加定位,才可以使用 元素.style.left
4、步骤实现
=>当开始的距离不是 0,就是有一个往回走的过程,所以我们可以获取到元素之前的初始位置
=>运动的距离不同,要同时到达目标位置,所以我们需要调整运动的速度,这个也是一个减速运动, 每次走剩余距离的 1/10
=>按照上面的方式,我们不能准确的到达目标位置,一定会出现小数0.9,而浏览器能识别的最小的单位是 1 px,所以需要我们向上取整
=>我们反方向运动的时候需要,向下取整
=>如果运动的是 opacity 属性 , 不能产生效果,存在两个原因:一个是单位,一个是opacity取值是0-1,存在小数问题
->单位解决办法:我们在运动的时候判断是不是opacity属性,如果是: 我们的就不加单位(px),反之添加
->小数问题:我们上来就需要判断一下是不是opacity属性,如果是 我们放大100倍,赋值的时候在缩小100倍
=>依旧是opacity属性在运动 , 到不了中间的位置,原因是:按照我们的计算方式 , 永远不能出现小数,所以我们可以上来就判断是不是opacity属性,如果是 我们给它放大100倍
=>同时我们这时发现,不能同时运动多个属性,需要考虑参数位的设计,以对象的方式传递参数
=>通过一个计数器,可以准确的知道什么时候运动真正的结束了
=>如果想要在结束之后做一些其他的事情,可以传入第三个参数,要是不需要我们可以不传,需要在单独加上一个判断即可
5、完整代码实现
- function move(ele,options,fn){
- let count = 0
- for(let k in options){
- // 执行一次进行一次count++
- count++
- // 这里判断输入的参数是否是opacity
- if(k === 'opacity'){
- options[k] = options[k] * 100
- }
- let time = setInterval(function(){
- // 得到开始距离,注意传入的是字符类型
- let start
- // 在这里判断是否是opacity,若是*100方便计算
- if(k === 'opacity'){
- start = window.getComputedStyle(ele)[k] * 100
- }else{
- start = parseInt(window.getComputedStyle(ele)[k])
- }
- let distance = (options[k] - start) / 10
- if(distance > 0){
- // 注意取整问题,因为会在0.9哪里一直循环,定时器无法停止,所以需要我们向上取整
- distance = Math.ceil(distance)
- }else{
- distance = Math.floor(distance)
- }
-
- // 判断如果开始距离是否等于输入的距离,从而结束定时器
- if(start === options[k]){
- clearInterval(time)
- // 这里进行count--
- count--
- if(count === 0){
- fn&&fn()
- }
- }else{
- // 判断是否是opacity,若是需要除以之前*100
- if(k === 'opacity'){
- ele.style[k] = (distance + start) / 100
- }else{
- ele.style[k] = distance + start + 'px'
- }
- }
- },20)
- }
-
- }
- box.onclick = function(){
- // 调用函数
- move(box,{top:200,left:300,width:400,opacity:0.3},function(){
- box.style.background = 'yellow'
- })
- }