import { bezier } from './cubicBezier' type TransformType = { x: number | undefined y: number | undefined scaleX: number | undefined scaleY: number | undefined } type CubicBuzier = [number, number, number, number] interface AnimateProps { from: TransformType to: TransformType duration: number onUpdate: (param: TransformType) => void cubicBezier?: CubicBuzier } export function animate(param: AnimateProps): void { let start = null const easing = param.cubicBezier ? bezier(...param.cubicBezier) : (v: number) => v const { x: fromX, y: fromY, scaleX: fromScaleX, scaleY: fromScaleY } = param.from const { x: toX, y: toY, scaleX: toScaleX, scaleY: toScaleY } = param.to function frame(timestamp) { if (!start) start = timestamp const progress = timestamp - start! const x = toX !== undefined ? fromX! + (toX - fromX!) * easing(progress / param.duration) : undefined // apply the easing function to the progress const y = toY !== undefined ? fromY! + (toY - fromY!) * easing(progress / param.duration) : undefined const scaleX = toScaleX !== undefined ? fromScaleX! + (toScaleX - fromScaleX!) * easing(progress / param.duration) : undefined const scaleY = toScaleY !== undefined ? fromScaleY! + (toScaleY - fromScaleY!) * easing(progress / param.duration) : undefined param.onUpdate({ x, y, scaleX, scaleY }) if (progress < param.duration) { requestAnimationFrame(frame) // continue animating } } requestAnimationFrame(frame) }