首先,贝塞尔曲线的算法如下:

export const linear = (p1, p2, t) => {
  const [x1, y1] = p1
  const [x2, y2] = p2
  const x = x1 + (x2 - x1) * t
  const y = y1 + (y2 - y1) * t
  return {x, y}
}
export const quadratic = (p1, p2, cp, t) => {
  const [x1, y1] = p1
  const [x2, y2] = p2
  const [cx, cy] = cp
  let x = (1 - t) * (1 - t) * x1 + 2 * t * (1 - t) * cx + t * t * x2
  let y = (1 - t) * (1 - t) * y1 + 2 * t * (1 - t) * cy + t * t * y2
  return {x, y}
}
export const cubic = (p1, p2, cp1, cp2, t) => {
  const [x1, y1] = p1
  const [x2, y2] = p2
  const [cx1, cy1] = cp1
  const [cx2, cy2] = cp2
  let x =
    x1 * (1 - t) * (1 - t) * (1 - t) +
    3 * cx1 * t * (1 - t) * (1 - t) +
    3 * cx2 * t * t * (1 - t) +
    x2 * t * t * t
  let y =
    y1 * (1 - t) * (1 - t) * (1 - t) +
    3 * cy1 * t * (1 - t) * (1 - t) +
    3 * cy2 * t * t * (1 - t) +
    y2 * t * t * t
  return {x, y}
}

参考文章:https://segmentfault.com/a/11...
然后,要让元素进行移动,使用requestAnimationFrame很方便。就是每次执行这个函数时,通过算法算出现在的坐标,将它赋予运动的元素的left和top就可以了。部分代码:

_move (target, count) {
    // count是指requestAnimationFrame的执行次数,t就是贝塞尔算法中的t
    const t = this._calcT(count, t)
    // 计算当前坐标
    const points = this._calcBezierPoint(t)
    target.style.left = points.x + 'px'
    target.style.top = points.y + 'px'
    // 如果t>=1,就表示运行完成了
    if (t < 1) {
      count++
      requestAnimationFrame(() => {
        this._move(target, count)
      })
    } else {
      if (isDef(this.onEnd)) {
        this.onEnd()
      }
    }
  }

  play () {
    // target是运动的元素
    // start是初始坐标
    // end是终点坐标
    const {target, start, end} = this
    if ([target, start, end].every(isDef)) {
      let count = 0
      target.style.position = 'absolute'
      requestAnimationFrame(() => {
        this._move(target, count)
      })
    } else {
      throw new Error('[error]: the target, start and end option must be defined.')
    }
    return this
  }

codepen
npm


小结点
154 声望3 粉丝