返回

实现一个轻量的加入购物车抛物线动画

计算二次函数参数

采用两点式计算二次函数参数 以屏幕坐下为坐标轴原点,对称轴用起始点元素的横坐标减去屏幕宽度的八分之一。

targetX 与X轴的一个交点,购物车在左下角所以就用的是目标点的横坐标。

/**
 * 计算二次函数参数
 * @param depart
 * @param targetX
 * @returns {[number, *, *]}
 */
const quadraticCurve = (depart, targetX) => {
  const k = depart.x - window.innerWidth / 8
  const x2 = targetX + 2 * (k - targetX)
  const a = depart.y / ((depart.x - targetX) * (depart.x - x2))

  return [a, targetX, x2]
}

执行动画

departEle 是圆点飞出的起始元素 className 是圆点的类名 frame 是帧数

/**
 * 执行动画
 * @param departEle
 * @param targetX
 * @param className
 * @param frame
 */
export const quadratic = (
  departEle,
  targetX = 0,
  className = 'float-icon',
  frame = 25
) => {
  const { right, bottom } = departEle.getBoundingClientRect()
  const [a, x1, x2] = quadraticCurve(
    { x: right, y: window.innerHeight - bottom },
    targetX
  )

  let currentFrame = 0
  const interval = right / frame
  const childNode = document.createElement('div')
  childNode.classList.add(className)
  document.getElementsByTagName('body')[0].appendChild(childNode)
  setTimeout(() => {
    childNode.remove()
  }, 1000)

  const animation = () => {
    if (currentFrame >= frame) return
    currentFrame += 1
    const x = right - interval * currentFrame
    childNode.style.left = `${x}px`
    childNode.style.bottom = `${Math.min(
      a * (x - x1) * (x - x2) - window.pageYOffset,
      window.innerHeight
    )}px`
    window.requestAnimationFrame(() => animation())
  }
  animation()
}

效果

Dec-17-2020 16-52-57.gif

Licensed under CC BY-NC-SA 4.0