UNPKG

animejs

Version:

JavaScript animation engine

89 lines (81 loc) 2.51 kB
/** * Anime.js - svg - ESM * @version v4.3.6 * @license MIT * @copyright 2026 - Julian Garnier */ import { isSvgSymbol } from '../core/consts.js'; import { atan2, PI } from '../core/helpers.js'; import { getPath } from './helpers.js'; /** * @import { * TargetsParam, * FunctionValue, * TweenObjectValue, * TweenModifier, * } from '../types/index.js' */ // Motion path animation /** * @param {SVGGeometryElement} $path * @param {Number} totalLength * @param {Number} progress * @param {Number} lookup * @param {Boolean} shouldClamp * @return {DOMPoint} */ const getPathPoint = ($path, totalLength, progress, lookup, shouldClamp) => { const point = progress + lookup; const pointOnPath = shouldClamp ? Math.max(0, Math.min(point, totalLength)) // Clamp between 0 and totalLength : (point % totalLength + totalLength) % totalLength; // Wrap around return $path.getPointAtLength(pointOnPath); }; /** * @param {SVGGeometryElement} $path * @param {String} pathProperty * @param {Number} [offset=0] * @return {FunctionValue} */ const getPathProgess = ($path, pathProperty, offset = 0) => { return $el => { const totalLength = +($path.getTotalLength()); const inSvg = $el[isSvgSymbol]; const ctm = $path.getCTM(); const shouldClamp = offset === 0; /** @type {TweenObjectValue} */ return { from: 0, to: totalLength, /** @type {TweenModifier} */ modifier: progress => { const offsetLength = offset * totalLength; const newProgress = progress + offsetLength; if (pathProperty === 'a') { const p0 = getPathPoint($path, totalLength, newProgress, -1, shouldClamp); const p1 = getPathPoint($path, totalLength, newProgress, 1, shouldClamp); return atan2(p1.y - p0.y, p1.x - p0.x) * 180 / PI; } else { const p = getPathPoint($path, totalLength, newProgress, 0, shouldClamp); return pathProperty === 'x' ? inSvg || !ctm ? p.x : p.x * ctm.a + p.y * ctm.c + ctm.e : inSvg || !ctm ? p.y : p.x * ctm.b + p.y * ctm.d + ctm.f } } } } }; /** * @param {TargetsParam} path * @param {Number} [offset=0] */ const createMotionPath = (path, offset = 0) => { const $path = getPath(path); if (!$path) return; return { translateX: getPathProgess($path, 'x', offset), translateY: getPathProgess($path, 'y', offset), rotate: getPathProgess($path, 'a', offset), } }; export { createMotionPath };