封装--运动函数

就是把一个元素运动的过程封装起来

需求: 页面上有一个 div

  => 当你触发事件(可以是任何事件)的时候

  => 可以改变 div 的位置

  => 需要运动的改变

  => 问题1: 这个运动函数需要多少个参数 ?

    -> 要运动的元素      ele

    -> 要运动的样式名    type

    -> 要运动的目标位置   target

问题: 如果我的元素起始位置不是 0 ?

  => 因为我在封装的时候, distance 始终是 0

  => 不管你元素的开始位置是什么

  => 运动的开始位置一定是 0

解决:

  => 再加一个参数

    -> 不好

    -> 尽量不添加参数

  => 直接去拿到元素的开始位置

    -> 当元素需要运动的是 left 属性

    -> 只要在运动开始之前, 把元素本身的 left 属性拿到

    -> 把我拿到的元素初始值, 当做 distance 的初始值

问题: 如何获取元素的初始位置 ?

  => 获取元素的 非行内 样式 left

  => 标准浏览器: window.getComputedStyle(元素).样式名

  => 注意: 你拿到的值是带有 px 的, 不要忘记使用 parseInt()

问题: 元素运动的初始值和目标值不一定是 整数 ?

  => 不容易刚好到达目标位置, 可能会差一点

解决: 把每次运动的距离改成 1

  => 把定时器的事件调整的快一些

问题: 如果调整为每次运动距离为 1, 那么当多个属性一起运动的时候

  => 有的先完成有的后完成

解决: 把匀速运动改成非匀速运动

  => 通过速度的不一致, 得到最终运动时间一致

实现:

  => 只要不让你每次都运动 1px

  => 不管你运动总距离是多少, 我都固定每次运动剩余距离的 10分之1

  => 每次的定时器拿到

    -> 当前的 left 位置是多少

    -> 目标位置 - 当前位置, 求出来的是 剩余距离

    -> 剩余距离 / 10, 求出, 本次应该运动的距离

    -> 判断:1

      + 判断当前位置是否到达目标位置

      + 如果到达目标位置, 停止定时器

      + 如果没有到达目标位置, 赋值: 当前位置 + 本次运动距离

问题: 没有办法到达目标位置 ?

  => 随着运动, 一定会到达一个临界点, 还差不到 10px 到目标位置了

  => 当你剩余距离还剩 9px 的时候

  => 计算出的本次运动距离 0.9px

  => 因为浏览器能描述的最小像素是 1px

  => 0.9 px 就不会运动了, 就停在原位

  => 导致下次还是剩余 9px, 计算的运动距离还是 0.9, 还是不会运动

解决:     向上取整

问题: 向负方向运动 ?

  => 因为你操作向上取整

  => 当你向负方向运动的时候

  => 一定能在过程中计算出 -0.9 的数字

  => -0.9 向上取整, 得到 0

  => 导致本次运动距离是 0, 下次拿到的运动距离依旧是 -0.9

  => 改成向下取整

问题: 正负方向不能兼容 ?

  => 判断, 当他 大于0 的时候, 向上取整

  => 当他 小于0 的时候, 向下取整

问题: 我想运动一下 opacity ?

  => 赋值的时候, 带有 px 单位

  => 因为 opacity 是不需要带有单位的

  => 赋值的时候, 需要判断一下, 如果是 opacity 不需要加单位

  => 如果不是 opacity 才加 px 单位

问题: 没有运动的过程了 ?

  => 因为你拿到的值是 1, 目标位置是 0

  => 本次的运动距离一定是 (0 - 1) / 10, 得到的是 -0.1, 取整以后, 得到的是 -1

  => 赋值的时候, opacity = 1 + -1, 直接等于 0

解决: 获取值的时候, 放大 100倍

  => 你如果当前是 1, 那么拿到的是 100

  => 你赋值的时候, 缩小 100 倍

  => 你赋值的时候如果是 90, 真实赋值是 0.9

问题: 没办法向正方向运动 ?

  => 注意: 当你需要运动 opacity 的时候

  => 最好你給值的时候, 按照 0 ~ 100 的区间給值

问题: 一个函数只能运动一个属性 ?

  => 因为我们设计的函数就是 单属性 运动函数

解决: 我想把函数设计成多属性运动函数

  => 方案1: 添加参数个数

    -> 不好

  => 方案2: 以对象的形式传递需要运动的内容

    {

      left: 500,

      top: 300,

      width: 400

    }

问题: 我如何捕获到运动完全结束了 ?

  => 我需要在运动结束的时候, 在控制台打印一下结束了

  => 因为你开启多少个定时器, 就会关闭多少个定时器

  => 每关闭一个定时器就会执行一次运动结束的打印

  => 运动多少个属性, 就会打印多少次

  => 中间有四次不是真的运动完全结束

问题2: 什么时候才是运动真的结束 ?

  => 最后一个定时器关闭以后

解决:

  => 准备一个 计数器, 每开启一个定时器, 计数器 ++

  => 每关闭一个定时器, 计数器 --

  => 等到计数器回归到 0 的时候, 最后一个定时器关闭了

需求: div 运动完全结束以后, 在控制台打印结束

      p 运动完全结束以后, 用 alert 的形式来告知结束

问题: 我想在运动结束以后, 做点事情 ?

  => 因为 move 函数是封装的, 一次封装多次调用

  => 我可以把我想在运动结束做的事情, 放在一个 "锦囊" 里面

  => 把这个 "锦囊" 交给 move 运动函数

  => 封装 move 的时候, 会在运动完全结束的时候, 把 "锦囊" 内的代码完全执行

  => 可以承载一段代码的 "盒子" 是 函数

let move = (ele, target, fn) => {
  let count = 0
  for (let k in target) {
    count++
    const timer = setInterval(() => {
      let current
      if (k === 'opacity') {
        current = window.getComputedStyle(ele)[k] * 100
      } else {
        current = parseInt(window.getComputedStyle(ele)[k])
      }
      let distance = (target[k] - current) / 10
      distance = distance > 0 ? Math.ceil(distance) : Math.floor(distance)
      if (current === target[k]) {
        clearInterval(timer)
        count--
        if (count === 0) fn()
      } else {
        if (k === 'opacity') {
          ele.style[k] = (current + distance) / 100
        } else {
          ele.style[k] = current + distance + 'px'
        }
      }
    }, 20)
  }
}

调用

// 将来我需要使用的时候
const box = document.querySelector('div')

box.onclick = function () {
  move(box, {
    left: 600,
    top: 300,
    width: 400,
    height: 200,
    opacity: 35
  }, () => { console.log('div 运动结束了') })
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值