抛物线:利用抛物线方程 y = ax^2 + bx + c 传入3点坐标(x1, y1)(x2, y2)(x3, y3)求解出参数 a, b, c
a: (y3 - y1 + (y2 - y1) * (x1 - x3) / (x2 - x1)) / (x3 * x3 - x1 * x1 - (x3 - x1) * (x1 + x2))
b: (y2 - y1 + a * x1 * x1 - a * x2 * x2) / (x2 - x1)
c: y1 - a * x1 * x1 - b * x1
从起点到终点, x匀速增加, 将x 带入方程得到y值,(x, y)即为动画每一帧的坐标位置
原点位置默认为页面左上角
完整代码:
// 元素抛物线动画
// startPos 动画元素起始位置
// targetPos 动画元素结束位置
// animationDom 动画元素
// animationTime 动画执行时间
// time 动画执行间隔
// callback动画执行完回调函数
function parabolaAnimation(startPos, targetPos, animationDom, animationTime = 400, time = 10, callback) {
const [x1, x2, y1, y2] = [parseInt(-startPos.x), parseInt(-targetPos.x), parseInt(-startPos.y), parseInt(-targetPos.y)]
const x3 = (x1 + x2) * 3 / 5
const y3 = y2 + 30
const dom = document.createElement('img')
dom.src = car
dom.width = 30
dom.height = 30
const animationDoms = animationDom ? animationDom : dom
const speedX = (x2 - x1) * time / animationTime
let times = 0
animationDoms.style.position = 'fixed'
animationDoms.style.left = `${-x1}px`
animationDoms.style.top = `${-y1}px`
animationDoms.style.zIndex = '10000'
document.body.appendChild(animationDoms)
// 利用抛物线方程: y = ax^2 + bx + c 带入三点坐标求得抛物线方程系数 a, b, c 。再根据方程,传入X 求Y
const a = (y3 - y1 + (y2 - y1) * (x1 - x3) / (x2 - x1)) / (x3 * x3 - x1 * x1 - (x3 - x1) * (x1 + x2))
const b = (y2 - y1 + a * x1 * x1 - a * x2 * x2) / (x2 - x1)
const c = y1 - a * x1 * x1 - b * x1
const timer = setInterval(() => {
times += 1
const x = x1 + speedX * times
const y = a * x * x + b * x + c
if (times * time > animationTime) {
clearInterval(timer)
document.body.removeChild(animationDoms)
callback && callback()
} else {
animationDoms.style.left = `${-x}px`
animationDoms.style.top = `${-y}px`
}
}, time)
}
执行完抛物线动画,可以在让购物车按钮加点抖动动画效果,抖动动画:
// 元素抖动动画
// maxDistance 抖动偏移距离
// interval 抖动快慢,数字越小越快,太小DOM反应不过来,看不出动画
// quarterCycle 一次完整来回抖动的四分之一周期
export function shakingAnimation(el, maxDistance = 5, interval = 15, quarterCycle = 8) {
let curDistance = 0
let direction = 1
const timer = setInterval(function () {
if (direction > 0) {
curDistance++
if (curDistance === maxDistance) {
direction = -1
maxDistance -= 1
}
} else {
curDistance--
if (curDistance === -maxDistance) {
direction = 1
}
}
el.style.transform = `translateY(${curDistance}px)`;
}, interval)
setTimeout(function () {
clearInterval(timer)
el.style.transform = `translateY(0)`;
}, maxDistance * interval * quarterCycle);
}
网友评论